Dynamic channels (#411)

This commit is contained in:
Michael Miller
2021-01-24 15:44:13 -08:00
committed by GitHub
parent fc6ae8ed18
commit ed3eeb1f1b
6 changed files with 229 additions and 48 deletions

View File

@@ -188,6 +188,13 @@ NeoEsp32I2s1Tm1814InvertedMethod KEYWORD1
NeoEsp32I2s1800KbpsInvertedMethod KEYWORD1 NeoEsp32I2s1800KbpsInvertedMethod KEYWORD1
NeoEsp32I2s1400KbpsInvertedMethod KEYWORD1 NeoEsp32I2s1400KbpsInvertedMethod KEYWORD1
NeoEsp32I2s1Apa106InvertedMethod KEYWORD1 NeoEsp32I2s1Apa106InvertedMethod KEYWORD1
NeoEsp32RmtNWs2811Method KEYWORD1
NeoEsp32RmtNWs2812xMethod KEYWORD1
NeoEsp32RmtNSk6812Method KEYWORD1
NeoEsp32RmtNTm1814Method KEYWORD1
NeoEsp32RmtNApa106Method KEYWORD1
NeoEsp32RmtN800KbpsMethod KEYWORD1
NeoEsp32RmtN400KbpsMethod KEYWORD1
NeoEsp32Rmt0Ws2811Method KEYWORD1 NeoEsp32Rmt0Ws2811Method KEYWORD1
NeoEsp32Rmt0Ws2812xMethod KEYWORD1 NeoEsp32Rmt0Ws2812xMethod KEYWORD1
NeoEsp32Rmt0Sk6812Method KEYWORD1 NeoEsp32Rmt0Sk6812Method KEYWORD1
@@ -244,6 +251,13 @@ NeoEsp32Rmt7Tm1814Method KEYWORD1
NeoEsp32Rmt7Apa106Method KEYWORD1 NeoEsp32Rmt7Apa106Method KEYWORD1
NeoEsp32Rmt7800KbpsMethod KEYWORD1 NeoEsp32Rmt7800KbpsMethod KEYWORD1
NeoEsp32Rmt7400KbpsMethod KEYWORD1 NeoEsp32Rmt7400KbpsMethod KEYWORD1
NeoEsp32RmtNWs2811InvertedMethod KEYWORD1
NeoEsp32RmtNWs2812xInvertedMethod KEYWORD1
NeoEsp32RmtNSk6812InvertedMethod KEYWORD1
NeoEsp32RmtNTm1814InvertedMethod KEYWORD1
NeoEsp32RmtNApa106InvertedMethod KEYWORD1
NeoEsp32RmtN800KbpsInvertedMethod KEYWORD1
NeoEsp32RmtN400KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt0Ws2811InvertedMethod KEYWORD1 NeoEsp32Rmt0Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt0Ws2812xInvertedMethod KEYWORD1 NeoEsp32Rmt0Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt0Sk6812InvertedMethod KEYWORD1 NeoEsp32Rmt0Sk6812InvertedMethod KEYWORD1
@@ -320,6 +334,12 @@ NeoEsp32BitBangLc8812InvertedMethod KEYWORD1
NeoEsp32BitBangApa106InvertedMethod KEYWORD1 NeoEsp32BitBangApa106InvertedMethod KEYWORD1
NeoEsp32BitBang800KbpsInvertedMethod KEYWORD1 NeoEsp32BitBang800KbpsInvertedMethod KEYWORD1
NeoEsp32BitBang400KbpsInvertedMethod KEYWORD1 NeoEsp32BitBang400KbpsInvertedMethod KEYWORD1
NeoNrf52xPwmNWs2812xMethod KEYWORD1
NeoNrf52xPwmNSk6812Method KEYWORD1
NeoNrf52xPwmNTm1814Method KEYWORD1
NeoNrf52xPwmN800KbpsMethod KEYWORD1
NeoNrf52xPwmN400KbpsMethod KEYWORD1
NeoNrf52xPwmNApa106Method KEYWORD1
NeoNrf52xPwm0Ws2812xMethod KEYWORD1 NeoNrf52xPwm0Ws2812xMethod KEYWORD1
NeoNrf52xPwm0Sk6812Method KEYWORD1 NeoNrf52xPwm0Sk6812Method KEYWORD1
NeoNrf52xPwm0Tm1814Method KEYWORD1 NeoNrf52xPwm0Tm1814Method KEYWORD1
@@ -344,6 +364,12 @@ NeoNrf52xPwm3Tm1814Method KEYWORD1
NeoNrf52xPwm3800KbpsMethod KEYWORD1 NeoNrf52xPwm3800KbpsMethod KEYWORD1
NeoNrf52xPwm3400KbpsMethod KEYWORD1 NeoNrf52xPwm3400KbpsMethod KEYWORD1
NeoNrf52xPwm3Apa106Method KEYWORD1 NeoNrf52xPwm3Apa106Method KEYWORD1
NeoNrf52xPwmNWs2812xInvertedMethod KEYWORD1
NeoNrf52xPwmNSk6812InvertedMethod KEYWORD1
NeoNrf52xPwmNTm1814InvertedMethod KEYWORD1
NeoNrf52xPwmN800KbpsInvertedMethod KEYWORD1
NeoNrf52xPwmN400KbpsInvertedMethod KEYWORD1
NeoNrf52xPwmNApa106InvertedMethod KEYWORD1
NeoNrf52xPwm0Ws2812xInvertedMethod KEYWORD1 NeoNrf52xPwm0Ws2812xInvertedMethod KEYWORD1
NeoNrf52xPwm0Sk6812InvertedMethod KEYWORD1 NeoNrf52xPwm0Sk6812InvertedMethod KEYWORD1
NeoNrf52xPwm0Tm1814InvertedMethod KEYWORD1 NeoNrf52xPwm0Tm1814InvertedMethod KEYWORD1

View File

@@ -85,6 +85,8 @@ License along with NeoPixel. If not, see
#include "internal/NeoEase.h" #include "internal/NeoEase.h"
#include "internal/NeoGamma.h" #include "internal/NeoGamma.h"
#include "internal/NeoBusChannel.h"
#include "internal/DotStarGenericMethod.h" #include "internal/DotStarGenericMethod.h"
#include "internal/Lpd8806GenericMethod.h" #include "internal/Lpd8806GenericMethod.h"
#include "internal/Lpd6803GenericMethod.h" #include "internal/Lpd6803GenericMethod.h"
@@ -120,8 +122,6 @@ License along with NeoPixel. If not, see
#endif #endif
template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelBus template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelBus
{ {
public: public:
@@ -135,6 +135,13 @@ public:
{ {
} }
NeoPixelBus(uint16_t countPixels, uint8_t pin, NeoBusChannel channel) :
_countPixels(countPixels),
_state(0),
_method(pin, countPixels, T_COLOR_FEATURE::PixelSize, T_COLOR_FEATURE::SettingsSize, channel)
{
}
NeoPixelBus(uint16_t countPixels, uint8_t pinClock, uint8_t pinData) : NeoPixelBus(uint16_t countPixels, uint8_t pinClock, uint8_t pinData) :
_countPixels(countPixels), _countPixels(countPixels),
_state(0), _state(0),

View File

@@ -0,0 +1,29 @@
#pragma once
// For those platforms/methods that support dynamic channel setting
enum NeoBusChannel
{
NeoBusChannel_0,
NeoBusChannel_1,
NeoBusChannel_2,
// NRF52x has only 3 or 4 channels of PWM
#if defined(ARDUINO_ARCH_NRF52840)
#if defined(NRF_PWM3)
NeoBusChannel_3
#endif
// ESP32 has either 8 or 4 channels (S2 has only 4)
#elif defined(ARDUINO_ARCH_ESP32)
NeoBusChannel_3,
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
NeoBusChannel_4,
NeoBusChannel_5,
NeoBusChannel_6,
NeoBusChannel_7,
#endif // CONFIG_IDF_TARGET_ESP32S2
#endif // ARDUINO_ARCH_ESP32
};

View File

@@ -27,6 +27,7 @@ License along with NeoPixel. If not, see
<http://www.gnu.org/licenses/>. <http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/ -------------------------------------------------------------------------*/
#include "NeoBusChannel.h"
#include "NeoEsp32RmtMethod.h" #include "NeoEsp32RmtMethod.h"
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32

View File

@@ -322,24 +322,32 @@ public:
class NeoEsp32RmtChannel0 class NeoEsp32RmtChannel0
{ {
public: public:
NeoEsp32RmtChannel0() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_0; const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_0;
}; };
class NeoEsp32RmtChannel1 class NeoEsp32RmtChannel1
{ {
public: public:
NeoEsp32RmtChannel1() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_1; const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_1;
}; };
class NeoEsp32RmtChannel2 class NeoEsp32RmtChannel2
{ {
public: public:
NeoEsp32RmtChannel2() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_2; const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_2;
}; };
class NeoEsp32RmtChannel3 class NeoEsp32RmtChannel3
{ {
public: public:
NeoEsp32RmtChannel3() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_3; const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_3;
}; };
@@ -348,29 +356,50 @@ public:
class NeoEsp32RmtChannel4 class NeoEsp32RmtChannel4
{ {
public: public:
NeoEsp32RmtChannel4() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_4; const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_4;
}; };
class NeoEsp32RmtChannel5 class NeoEsp32RmtChannel5
{ {
public: public:
NeoEsp32RmtChannel5() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_5; const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_5;
}; };
class NeoEsp32RmtChannel6 class NeoEsp32RmtChannel6
{ {
public: public:
NeoEsp32RmtChannel6() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_6; const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_6;
}; };
class NeoEsp32RmtChannel7 class NeoEsp32RmtChannel7
{ {
public: public:
NeoEsp32RmtChannel7() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_7; const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_7;
}; };
#endif #endif
// dynamic channel support
class NeoEsp32RmtChannelN
{
public:
NeoEsp32RmtChannelN(NeoBusChannel channel) :
RmtChannelNumber(static_cast<rmt_channel_t>(channel))
{
}
NeoEsp32RmtChannelN() = delete; // no default constructor
const rmt_channel_t RmtChannelNumber;
};
template<typename T_SPEED, typename T_CHANNEL> class NeoEsp32RmtMethodBase template<typename T_SPEED, typename T_CHANNEL> class NeoEsp32RmtMethodBase
{ {
public: public:
@@ -378,20 +407,24 @@ public:
_sizeData(pixelCount * elementSize + settingsSize), _sizeData(pixelCount * elementSize + settingsSize),
_pin(pin) _pin(pin)
{ {
_dataEditing = static_cast<uint8_t*>(malloc(_sizeData)); construct();
memset(_dataEditing, 0x00, _sizeData); }
_dataSending = static_cast<uint8_t*>(malloc(_sizeData)); NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) :
// no need to initialize it, it gets overwritten on every send _sizeData(pixelCount* elementSize + settingsSize),
_pin(pin),
_channel(channel)
{
construct();
} }
~NeoEsp32RmtMethodBase() ~NeoEsp32RmtMethodBase()
{ {
// wait until the last send finishes before destructing everything // wait until the last send finishes before destructing everything
// arbitrary time out of 10 seconds // arbitrary time out of 10 seconds
ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_wait_tx_done(T_CHANNEL::RmtChannelNumber, 10000 / portTICK_PERIOD_MS)); ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_wait_tx_done(_channel.RmtChannelNumber, 10000 / portTICK_PERIOD_MS));
ESP_ERROR_CHECK(rmt_driver_uninstall(T_CHANNEL::RmtChannelNumber)); ESP_ERROR_CHECK(rmt_driver_uninstall(_channel.RmtChannelNumber));
free(_dataEditing); free(_dataEditing);
free(_dataSending); free(_dataSending);
@@ -400,7 +433,7 @@ public:
bool IsReadyToUpdate() const bool IsReadyToUpdate() const
{ {
return (ESP_OK == rmt_wait_tx_done(T_CHANNEL::RmtChannelNumber, 0)); return (ESP_OK == rmt_wait_tx_done(_channel.RmtChannelNumber, 0));
} }
void Initialize() void Initialize()
@@ -408,7 +441,7 @@ public:
rmt_config_t config; rmt_config_t config;
config.rmt_mode = RMT_MODE_TX; config.rmt_mode = RMT_MODE_TX;
config.channel = T_CHANNEL::RmtChannelNumber; config.channel = _channel.RmtChannelNumber;
config.gpio_num = static_cast<gpio_num_t>(_pin); config.gpio_num = static_cast<gpio_num_t>(_pin);
config.mem_block_num = 1; config.mem_block_num = 1;
config.tx_config.loop_en = false; config.tx_config.loop_en = false;
@@ -422,8 +455,8 @@ public:
config.clk_div = T_SPEED::RmtClockDivider; config.clk_div = T_SPEED::RmtClockDivider;
ESP_ERROR_CHECK(rmt_config(&config)); ESP_ERROR_CHECK(rmt_config(&config));
ESP_ERROR_CHECK(rmt_driver_install(T_CHANNEL::RmtChannelNumber, 0, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1)); ESP_ERROR_CHECK(rmt_driver_install(_channel.RmtChannelNumber, 0, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1));
ESP_ERROR_CHECK(rmt_translator_init(T_CHANNEL::RmtChannelNumber, T_SPEED::Translate)); ESP_ERROR_CHECK(rmt_translator_init(_channel.RmtChannelNumber, T_SPEED::Translate));
} }
void Update(bool maintainBufferConsistency) void Update(bool maintainBufferConsistency)
@@ -431,10 +464,10 @@ public:
// wait for not actively sending data // wait for not actively sending data
// this will time out at 10 seconds, an arbitrarily long period of time // this will time out at 10 seconds, an arbitrarily long period of time
// and do nothing if this happens // and do nothing if this happens
if (ESP_OK == ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_wait_tx_done(T_CHANNEL::RmtChannelNumber, 10000 / portTICK_PERIOD_MS))) if (ESP_OK == ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_wait_tx_done(_channel.RmtChannelNumber, 10000 / portTICK_PERIOD_MS)))
{ {
// now start the RMT transmit with the editing buffer before we swap // now start the RMT transmit with the editing buffer before we swap
ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_write_sample(T_CHANNEL::RmtChannelNumber, _dataEditing, _sizeData, false)); ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_write_sample(_channel.RmtChannelNumber, _dataEditing, _sizeData, false));
if (maintainBufferConsistency) if (maintainBufferConsistency)
{ {
@@ -462,13 +495,32 @@ public:
private: private:
const size_t _sizeData; // Size of '_data*' buffers const size_t _sizeData; // Size of '_data*' buffers
const uint8_t _pin; // output pin number const uint8_t _pin; // output pin number
const T_CHANNEL _channel; // holds instance for multi channel support
// Holds data stream which include LED color values and other settings as needed // Holds data stream which include LED color values and other settings as needed
uint8_t* _dataEditing; // exposed for get and set uint8_t* _dataEditing; // exposed for get and set
uint8_t* _dataSending; // used for async send using RMT uint8_t* _dataSending; // used for async send using RMT
void construct()
{
_dataEditing = static_cast<uint8_t*>(malloc(_sizeData));
memset(_dataEditing, 0x00, _sizeData);
_dataSending = static_cast<uint8_t*>(malloc(_sizeData));
// no need to initialize it, it gets overwritten on every send
}
}; };
// normal // normal
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannelN> NeoEsp32RmtNWs2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannelN> NeoEsp32RmtNWs2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannelN> NeoEsp32RmtNSk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedTm1814, NeoEsp32RmtChannelN> NeoEsp32RmtNTm1814Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannelN> NeoEsp32RmtNApa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannelN> NeoEsp32RmtN800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannelN> NeoEsp32RmtN400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2811Method; typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xMethod; typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812Method; typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812Method;
@@ -539,6 +591,14 @@ typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel7> NeoE
#endif #endif
// inverted // inverted
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannelN> NeoEsp32RmtNWs2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannelN> NeoEsp32RmtNWs2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannelN> NeoEsp32RmtNSk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedTm1814, NeoEsp32RmtChannelN> NeoEsp32RmtNTm1814InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannelN> NeoEsp32RmtNApa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannelN> NeoEsp32RmtN800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannelN> NeoEsp32RmtN400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2811InvertedMethod; typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xInvertedMethod; typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812InvertedMethod; typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812InvertedMethod;

View File

@@ -229,6 +229,34 @@ public:
}; };
#endif #endif
// dynamic channel support
class NeoNrf52xPwmN
{
public:
NeoNrf52xPwmN(NeoBusChannel channel)
{
NRF_PWM_Type* PWM[] = {
NRF_PWM0,
NRF_PWM1,
NRF_PWM2
#ifdef NRF_PWM3
,NRF_PWM3
#endif
};
_pwm = PWM[channel];
}
inline NRF_PWM_Type* Pwm() const
{
return _pwm;
}
protected:
NRF_PWM_Type* _pwm;
NeoNrf52xPwmN() {};
};
template<typename T_SPEED, typename T_BUS> class NeoNrf52xMethodBase template<typename T_SPEED, typename T_BUS> class NeoNrf52xMethodBase
{ {
public: public:
@@ -236,13 +264,15 @@ public:
_sizeData(pixelCount * elementSize + settingsSize), _sizeData(pixelCount * elementSize + settingsSize),
_pin(pin) _pin(pin)
{ {
pinMode(pin, OUTPUT); construct();
}
_data = static_cast<uint8_t*>(malloc(_sizeData)); NeoNrf52xMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) :
memset(_data, 0, _sizeData); _sizeData(pixelCount* elementSize + settingsSize),
_pin(pin),
_dmaBufferSize = c_dmaBytesPerDataByte * _sizeData + sizeof(nrf_pwm_values_common_t); _bus(channel)
_dmaBuffer = static_cast<nrf_pwm_values_common_t*>(malloc(_dmaBufferSize)); {
construct();
} }
~NeoNrf52xMethodBase() ~NeoNrf52xMethodBase()
@@ -262,7 +292,7 @@ public:
bool IsReadyToUpdate() const bool IsReadyToUpdate() const
{ {
return (T_BUS::Pwm()->EVENTS_STOPPED); return (_bus.Pwm()->EVENTS_STOPPED);
} }
void Initialize() void Initialize()
@@ -307,50 +337,62 @@ public:
private: private:
const size_t _sizeData; // Size of '_data' buffer below const size_t _sizeData; // Size of '_data' buffer below
const uint8_t _pin; // output pin number const uint8_t _pin; // output pin number
const T_BUS _bus; // holds instance for multi channel support
uint8_t* _data; // Holds LED color values uint8_t* _data; // Holds LED color values
size_t _dmaBufferSize; // total size of _dmaBuffer size_t _dmaBufferSize; // total size of _dmaBuffer
nrf_pwm_values_common_t* _dmaBuffer; // Holds pixel data in native format for PWM hardware nrf_pwm_values_common_t* _dmaBuffer; // Holds pixel data in native format for PWM hardware
void construct()
{
pinMode(_pin, OUTPUT);
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
_dmaBufferSize = c_dmaBytesPerDataByte * _sizeData + sizeof(nrf_pwm_values_common_t);
_dmaBuffer = static_cast<nrf_pwm_values_common_t*>(malloc(_dmaBufferSize));
}
void dmaInit() void dmaInit()
{ {
// only use channel zero // only use channel zero
T_BUS::Pwm()->PSEL.OUT[0] = digitalPinToPinName(_pin); _bus.Pwm()->PSEL.OUT[0] = digitalPinToPinName(_pin);
T_BUS::Pwm()->PSEL.OUT[1] = NC; _bus.Pwm()->PSEL.OUT[1] = NC;
T_BUS::Pwm()->PSEL.OUT[2] = NC; _bus.Pwm()->PSEL.OUT[2] = NC;
T_BUS::Pwm()->PSEL.OUT[3] = NC; _bus.Pwm()->PSEL.OUT[3] = NC;
T_BUS::Pwm()->ENABLE = 1; _bus.Pwm()->ENABLE = 1;
T_BUS::Pwm()->MODE = NRF_PWM_MODE_UP; _bus.Pwm()->MODE = NRF_PWM_MODE_UP;
T_BUS::Pwm()->PRESCALER = NRF_PWM_CLK_16MHz; _bus.Pwm()->PRESCALER = NRF_PWM_CLK_16MHz;
T_BUS::Pwm()->COUNTERTOP = T_SPEED::CountTop; _bus.Pwm()->COUNTERTOP = T_SPEED::CountTop;
T_BUS::Pwm()->LOOP = 1; // single fire so events get set _bus.Pwm()->LOOP = 1; // single fire so events get set
T_BUS::Pwm()->DECODER = NRF_PWM_LOAD_COMMON; _bus.Pwm()->DECODER = NRF_PWM_LOAD_COMMON;
// sequence zero is the primary data with a BitReset entry on the end for // sequence zero is the primary data with a BitReset entry on the end for
// the delay repeating // the delay repeating
T_BUS::Pwm()->SEQ[0].PTR = reinterpret_cast<uint32_t>(_dmaBuffer); _bus.Pwm()->SEQ[0].PTR = reinterpret_cast<uint32_t>(_dmaBuffer);
T_BUS::Pwm()->SEQ[0].CNT = _dmaBufferSize / sizeof(nrf_pwm_values_common_t); _bus.Pwm()->SEQ[0].CNT = _dmaBufferSize / sizeof(nrf_pwm_values_common_t);
T_BUS::Pwm()->SEQ[0].REFRESH = 0; // ignored _bus.Pwm()->SEQ[0].REFRESH = 0; // ignored
T_BUS::Pwm()->SEQ[0].ENDDELAY = T_SPEED::CountReset; // ignored still? _bus.Pwm()->SEQ[0].ENDDELAY = T_SPEED::CountReset; // ignored still?
// sequence one is pointing to the BitReset entry at the end of the primary data // sequence one is pointing to the BitReset entry at the end of the primary data
T_BUS::Pwm()->SEQ[1].PTR = reinterpret_cast<uint32_t>(_dmaBuffer + (T_BUS::Pwm()->SEQ[0].CNT - 1)); _bus.Pwm()->SEQ[1].PTR = reinterpret_cast<uint32_t>(_dmaBuffer + (_bus.Pwm()->SEQ[0].CNT - 1));
T_BUS::Pwm()->SEQ[1].CNT = 1; _bus.Pwm()->SEQ[1].CNT = 1;
T_BUS::Pwm()->SEQ[1].REFRESH = 0; // ignored _bus.Pwm()->SEQ[1].REFRESH = 0; // ignored
T_BUS::Pwm()->SEQ[1].ENDDELAY = 0; // ignored _bus.Pwm()->SEQ[1].ENDDELAY = 0; // ignored
// stop when the loop finishes // stop when the loop finishes
T_BUS::Pwm()->SHORTS = PWM_SHORTS_LOOPSDONE_STOP_Msk; _bus.Pwm()->SHORTS = PWM_SHORTS_LOOPSDONE_STOP_Msk;
T_BUS::Pwm()->INTEN = 0; _bus.Pwm()->INTEN = 0;
dmaResetEvents(); dmaResetEvents();
} }
void dmaDeinit() void dmaDeinit()
{ {
T_BUS::Pwm()->ENABLE = 0; _bus.Pwm()->ENABLE = 0;
T_BUS::Pwm()->PSEL.OUT[0] = NC; _bus.Pwm()->PSEL.OUT[0] = NC;
} }
void FillBuffer() void FillBuffer()
@@ -380,20 +422,28 @@ private:
void dmaResetEvents() void dmaResetEvents()
{ {
T_BUS::Pwm()->EVENTS_LOOPSDONE = 0; _bus.Pwm()->EVENTS_LOOPSDONE = 0;
T_BUS::Pwm()->EVENTS_SEQEND[0] = 0; _bus.Pwm()->EVENTS_SEQEND[0] = 0;
T_BUS::Pwm()->EVENTS_SEQEND[1] = 0; _bus.Pwm()->EVENTS_SEQEND[1] = 0;
T_BUS::Pwm()->EVENTS_STOPPED = 0; _bus.Pwm()->EVENTS_STOPPED = 0;
} }
void dmaStart() void dmaStart()
{ {
dmaResetEvents(); dmaResetEvents();
T_BUS::Pwm()->TASKS_SEQSTART[0] = 1; _bus.Pwm()->TASKS_SEQSTART[0] = 1;
} }
}; };
// normal // normal
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedWs2811, NeoNrf52xPwmN> NeoNrf52xPwmNWs2811Method;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedWs2812x, NeoNrf52xPwmN> NeoNrf52xPwmNWs2812xMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedSk6812, NeoNrf52xPwmN> NeoNrf52xPwmNSk6812Method;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedTm1814, NeoNrf52xPwmN> NeoNrf52xPwmNTm1814Method;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedApa106, NeoNrf52xPwmN> NeoNrf52xPwmNApa106Method;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeed800Kbps, NeoNrf52xPwmN> NeoNrf52xPwmN800KbpsMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeed400Kbps, NeoNrf52xPwmN> NeoNrf52xPwmN400KbpsMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedWs2811, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2811Method; typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedWs2811, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2811Method;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedWs2812x, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2812xMethod; typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedWs2812x, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2812xMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedSk6812, NeoNrf52xPwm0> NeoNrf52xPwm0Sk6812Method; typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedSk6812, NeoNrf52xPwm0> NeoNrf52xPwm0Sk6812Method;
@@ -429,6 +479,14 @@ typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeed400Kbps, NeoNrf52xPwm3> NeoNrf52xPw
#endif #endif
// inverted // inverted
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedWs2811, NeoNrf52xPwmN> NeoNrf52xPwmNWs2811InvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedWs2812x, NeoNrf52xPwmN> NeoNrf52xPwmNWs2812xInvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedSk6812, NeoNrf52xPwmN> NeoNrf52xPwmNSk6812InvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedTm1814, NeoNrf52xPwmN> NeoNrf52xPwmNTm1814InvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedApa106, NeoNrf52xPwmN> NeoNrf52xPwmNApa106InvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeed800Kbps, NeoNrf52xPwmN> NeoNrf52xPwmN800KbpsInvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeed400Kbps, NeoNrf52xPwmN> NeoNrf52xPwmN400KbpsInvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedWs2811, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2811InvertedMethod; typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedWs2811, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2811InvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedWs2812x, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2812xInvertedMethod; typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedWs2812x, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2812xInvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedSk6812, NeoNrf52xPwm0> NeoNrf52xPwm0Sk6812InvertedMethod; typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedSk6812, NeoNrf52xPwm0> NeoNrf52xPwm0Sk6812InvertedMethod;