* ili9341 update

* update ili9341

* Update support_tasmota.ino

* fix scripter bug

* Deep+

* Update ILI9341_2.cpp

Fix invert display

* Update xdsp_04_ili9341.ino

Fix display modes

* fix ili9341 m5stack

* Refactor DHT negative temps

* Standardize on unconnected pin being -1

* Back to chain+

* Strict

* strict

* Update platformio_tasmota32.ini

* Fix renderer

* Change NeoPixelBus library from v2.6.0 to v2.6.1.4

* display batch

* Update xdrv_13_display.ino

* ldf strict

Co-authored-by: gemu2015 <gmutz2010@googlemail.com>
Co-authored-by: Theo Arends <11044339+arendst@users.noreply.github.com>
This commit is contained in:
Jason2866 2021-02-14 16:04:03 +01:00 committed by GitHub
parent 98544a81f5
commit 0e0275cf43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
179 changed files with 2530 additions and 4474 deletions

View File

@ -10,7 +10,11 @@ All notable changes to this project will be documented in this file.
- Support for Frysk language translations by Christiaan Heerze
- ESP8266 Fallback to ``*.bin.gz`` binary when OTA upload of ``*.bin`` binary fails
- Berry language improved Tasmota integration
### Changed
- IRremoteESP8266 library from v2.7.14 to v2.7.15
- NeoPixelBus library from v2.6.0 to v2.6.1.4
- ILI9341 library from Adafruit_ILI9341-1.2.0-Tasmota-1.0 to ILI9341-gemu-1.0
## [9.2.0.6] 20210210
### Changed

View File

@ -141,6 +141,9 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
### Changed
- Remove support for direct migration from versions before v8.1.0 (Doris)
- IRremoteESP8266 library from v2.7.14 to v2.7.15
- NeoPixelBus library from v2.6.0 to v2.6.1.4
- ILI9341 library from Adafruit_ILI9341-1.2.0-Tasmota-1.0 to ILI9341-gemu-1.0
- Command ``Sleep 0`` removes any sleep from wifi modem except when ESP32 BLE is active
- Logging from heap to stack freeing 700 bytes RAM
- Disabled ``USE_LIGHT`` light support for ZBBridge saving 17.6kB [#10374](https://github.com/arendst/Tasmota/issues/10374)

View File

@ -10,7 +10,10 @@ Supports most Arduino platforms.
Please read this best practices link before connecting your NeoPixels, it will save you a lot of time and effort.
[Adafruit NeoPixel Best Practices](https://learn.adafruit.com/adafruit-neopixel-uberguide/best-practices)
For quick questions and support jump on Gitter and ask away.
For quick questions and support:
* [Try the new Github Discussions](https://github.com/Makuna/NeoPixelBus/discussions)
* [Discord NeoPixelBus Invitation](https://discord.gg/c6FrysvZyV) or if you are already a member of [Discord Server NeoPixelBus](https://discord.com/channels/789177382221119519/789177382221119521)
* Or jump on Gitter
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Makuna/NeoPixelBus?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
For bugs, make sure there isn't an active issue and then create one.

View File

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -10,6 +10,8 @@ NeoPixelBus KEYWORD1
NeoPixelSegmentBus KEYWORD1
RgbwColor KEYWORD1
RgbColor KEYWORD1
Rgb16Color KEYWORD1
Rgb48Color KEYWORD1
HslColor KEYWORD1
HsbColor KEYWORD1
HtmlColor KEYWORD1
@ -24,7 +26,12 @@ NeoRbgFeature KEYWORD1
NeoWrgbTm1814Feature KEYWORD1
DotStarBgrFeature KEYWORD1
DotStarLbgrFeature KEYWORD1
Lpd6803GrbFeature KEYWORD1
Lpd6803GbrFeature KEYWORD1
Lpd6803BrgFeature KEYWORD1
Lpd6803RgbFeature KEYWORD1
Lpd8806GrbFeature KEYWORD1
Lpd8806BrgFeature KEYWORD1
P9813BgrFeature KEYWORD1
SevenSegmentFeature KEYWORD1
Neo800KbpsMethod KEYWORD1
@ -159,6 +166,12 @@ NeoEsp8266BitBangLc8812InvertedMethod KEYWORD1
NeoEsp8266BitBangApa106InvertedMethod KEYWORD1
NeoEsp8266BitBang800KbpsInvertedMethod KEYWORD1
NeoEsp8266BitBang400KbpsInvertedMethod KEYWORD1
NeoEsp32I2sNWs2812xMethod KEYWORD1
NeoEsp32I2sNSk6812Method KEYWORD1
NeoEsp32I2sNTm1814Method KEYWORD1
NeoEsp32I2sN800KbpsMethod KEYWORD1
NeoEsp32I2sN400KbpsMethod KEYWORD1
NeoEsp32I2sNApa106Method KEYWORD1
NeoEsp32I2s0Ws2812xMethod KEYWORD1
NeoEsp32I2s0Sk6812Method KEYWORD1
NeoEsp32I2s0Tm1814Method KEYWORD1
@ -171,6 +184,12 @@ NeoEsp32I2s1Tm1814Method KEYWORD1
NeoEsp32I2s1800KbpsMethod KEYWORD1
NeoEsp32I2s1400KbpsMethod KEYWORD1
NeoEsp32I2s1Apa106Method KEYWORD1
NeoEsp32I2sNWs2812xInvertedMethod KEYWORD1
NeoEsp32I2sNSk6812InvertedMethod KEYWORD1
NeoEsp32I2sNTm1814InvertedMethod KEYWORD1
NeoEsp32I2sN800KbpsInvertedMethod KEYWORD1
NeoEsp32I2sN400KbpsInvertedMethod KEYWORD1
NeoEsp32I2sNApa106InvertedMethod KEYWORD1
NeoEsp32I2s0Ws2812xInvertedMethod KEYWORD1
NeoEsp32I2s0Sk6812InvertedMethod KEYWORD1
NeoEsp32I2s0Tm1814InvertedMethod KEYWORD1
@ -183,6 +202,13 @@ NeoEsp32I2s1Tm1814InvertedMethod KEYWORD1
NeoEsp32I2s1800KbpsInvertedMethod KEYWORD1
NeoEsp32I2s1400KbpsInvertedMethod KEYWORD1
NeoEsp32I2s1Apa106InvertedMethod KEYWORD1
NeoEsp32RmtNWs2811Method KEYWORD1
NeoEsp32RmtNWs2812xMethod KEYWORD1
NeoEsp32RmtNSk6812Method KEYWORD1
NeoEsp32RmtNTm1814Method KEYWORD1
NeoEsp32RmtNApa106Method KEYWORD1
NeoEsp32RmtN800KbpsMethod KEYWORD1
NeoEsp32RmtN400KbpsMethod KEYWORD1
NeoEsp32Rmt0Ws2811Method KEYWORD1
NeoEsp32Rmt0Ws2812xMethod KEYWORD1
NeoEsp32Rmt0Sk6812Method KEYWORD1
@ -239,6 +265,13 @@ NeoEsp32Rmt7Tm1814Method KEYWORD1
NeoEsp32Rmt7Apa106Method KEYWORD1
NeoEsp32Rmt7800KbpsMethod KEYWORD1
NeoEsp32Rmt7400KbpsMethod KEYWORD1
NeoEsp32RmtNWs2811InvertedMethod KEYWORD1
NeoEsp32RmtNWs2812xInvertedMethod KEYWORD1
NeoEsp32RmtNSk6812InvertedMethod KEYWORD1
NeoEsp32RmtNTm1814InvertedMethod KEYWORD1
NeoEsp32RmtNApa106InvertedMethod KEYWORD1
NeoEsp32RmtN800KbpsInvertedMethod KEYWORD1
NeoEsp32RmtN400KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt0Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt0Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt0Sk6812InvertedMethod KEYWORD1
@ -315,6 +348,12 @@ NeoEsp32BitBangLc8812InvertedMethod KEYWORD1
NeoEsp32BitBangApa106InvertedMethod KEYWORD1
NeoEsp32BitBang800KbpsInvertedMethod KEYWORD1
NeoEsp32BitBang400KbpsInvertedMethod KEYWORD1
NeoNrf52xPwmNWs2812xMethod KEYWORD1
NeoNrf52xPwmNSk6812Method KEYWORD1
NeoNrf52xPwmNTm1814Method KEYWORD1
NeoNrf52xPwmN800KbpsMethod KEYWORD1
NeoNrf52xPwmN400KbpsMethod KEYWORD1
NeoNrf52xPwmNApa106Method KEYWORD1
NeoNrf52xPwm0Ws2812xMethod KEYWORD1
NeoNrf52xPwm0Sk6812Method KEYWORD1
NeoNrf52xPwm0Tm1814Method KEYWORD1
@ -339,6 +378,12 @@ NeoNrf52xPwm3Tm1814Method KEYWORD1
NeoNrf52xPwm3800KbpsMethod KEYWORD1
NeoNrf52xPwm3400KbpsMethod KEYWORD1
NeoNrf52xPwm3Apa106Method KEYWORD1
NeoNrf52xPwmNWs2812xInvertedMethod KEYWORD1
NeoNrf52xPwmNSk6812InvertedMethod KEYWORD1
NeoNrf52xPwmNTm1814InvertedMethod KEYWORD1
NeoNrf52xPwmN800KbpsInvertedMethod KEYWORD1
NeoNrf52xPwmN400KbpsInvertedMethod KEYWORD1
NeoNrf52xPwmNApa106InvertedMethod KEYWORD1
NeoNrf52xPwm0Ws2812xInvertedMethod KEYWORD1
NeoNrf52xPwm0Sk6812InvertedMethod KEYWORD1
NeoNrf52xPwm0Tm1814InvertedMethod KEYWORD1
@ -368,21 +413,36 @@ DotStarSpiMethod KEYWORD1
DotStarSpi20MhzMethod KEYWORD1
DotStarSpi10MhzMethod KEYWORD1
DotStarSpi2MhzMethod KEYWORD1
DotStarSpi1MhzMethod KEYWORD1
DotStarSpi500KhzMethod KEYWORD1
NeoWs2801Method KEYWORD1
NeoWs2801SpiMethod KEYWORD1
NeoWs2801Spi20MhzMethod KEYWORD1
NeoWs2801Spi10MhzMethod KEYWORD1
NeoWs2801Spi2MhzMethod KEYWORD1
NeoWs2801Spi1MhzMethod KEYWORD1
NeoWs2801Spi500KhzMethod KEYWORD1
Lpd6803SpiMethod KEYWORD1
Lpd6803Method KEYWORD1
Lpd6803Spi20MhzMethod KEYWORD1
Lpd6803Spi10MhzMethod KEYWORD1
Lpd6803Spi2MhzMethod KEYWORD1
Lpd6803Spi1MhzMethod KEYWORD1
Lpd6803Spi500KhzMethod KEYWORD1
Lpd8806Method KEYWORD1
Lpd8806SpiMethod KEYWORD1
Lpd8806Spi20MhzMethod KEYWORD1
Lpd8806Spi10MhzMethod KEYWORD1
Lpd8806Spi2MhzMethod KEYWORD1
Lpd8806Spi1MhzMethod KEYWORD1
Lpd8806Spi500KhzMethod KEYWORD1
P9813Method KEYWORD1
P9813SpiMethod KEYWORD1
P9813Spi20MhzMethod KEYWORD1
P9813Spi10MhzMethod KEYWORD1
P9813Spi2MhzMethod KEYWORD1
P9813Spi1MhzMethod KEYWORD1
P9813Spi500KhzMethod KEYWORD1
NeoPixelAnimator KEYWORD1
AnimUpdateCallback KEYWORD1
AnimationParam KEYWORD1
@ -537,3 +597,11 @@ NeoTopologyHint_InPanel LITERAL1
NeoTopologyHint_LastOnPanel LITERAL1
NeoTopologyHint_OutOfBounds LITERAL1
PixelIndex_OutOfBounds LITERAL1
NeoBusChannel_0 LITERAL1
NeoBusChannel_1 LITERAL1
NeoBusChannel_2 LITERAL1
NeoBusChannel_3 LITERAL1
NeoBusChannel_4 LITERAL1
NeoBusChannel_5 LITERAL1
NeoBusChannel_6 LITERAL1
NeoBusChannel_7 LITERAL1

View File

@ -7,8 +7,13 @@
"type": "git",
"url": "https://github.com/Makuna/NeoPixelBus"
},
"version": "2.6.0",
"version": "2.6.1",
"frameworks": "arduino",
"platforms": ["espressif8266", "espressif32"]
"platforms": "*",
"dependencies": [
{
"name": "SPI"
}
]
}

View File

@ -1,5 +1,5 @@
name=NeoPixelBus by Makuna
version=2.6.0
version=2.6.1
author=Michael C. Miller (makuna@live.com)
maintainer=Michael C. Miller (makuna@live.com)
sentence=A library that makes controlling NeoPixels (APA106, WS2811, WS2812, WS2813 & SK6812) and DotStars (APA102, LPD8806, SK9822, WS2801, P9813) easy.

View File

@ -51,9 +51,13 @@ License along with NeoPixel. If not, see
#include "internal/NeoSettings.h"
#include "internal/RgbColor.h"
#include "internal/Rgb16Color.h"
#include "internal/Rgb48Color.h"
#include "internal/HslColor.h"
#include "internal/HsbColor.h"
#include "internal/HtmlColor.h"
#include "internal/RgbwColor.h"
#include "internal/SegmentDigit.h"
@ -61,6 +65,7 @@ License along with NeoPixel. If not, see
#include "internal/NeoTm1814ColorFeatures.h"
#include "internal/DotStarColorFeatures.h"
#include "internal/Lpd8806ColorFeatures.h"
#include "internal/Lpd6803ColorFeatures.h"
#include "internal/P9813ColorFeatures.h"
#include "internal/NeoSegmentFeatures.h"
@ -80,8 +85,11 @@ License along with NeoPixel. If not, see
#include "internal/NeoEase.h"
#include "internal/NeoGamma.h"
#include "internal/NeoBusChannel.h"
#include "internal/DotStarGenericMethod.h"
#include "internal/Lpd8806GenericMethod.h"
#include "internal/Lpd6803GenericMethod.h"
#include "internal/Ws2801GenericMethod.h"
#include "internal/P9813GenericMethod.h"
@ -114,8 +122,6 @@ License along with NeoPixel. If not, see
#endif
template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelBus
{
public:
@ -129,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) :
_countPixels(countPixels),
_state(0),
@ -156,14 +169,14 @@ public:
void Begin()
{
_method.Initialize();
Dirty();
ClearTo(0);
}
// used by DotStartSpiMethod 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);
Dirty();
ClearTo(0);
}
void Show(bool maintainBufferConsistency = true)

View File

@ -43,7 +43,7 @@ public:
_wire(pinClock, pinData)
{
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
// data cleared later in Begin()
}
#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
@ -128,6 +128,9 @@ typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed40Mhz>> DotStarSpi40MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> DotStarSpi20MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> DotStarSpi10MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> DotStarSpi2MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> DotStarSpi1MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed500Khz>> DotStarSpi500KhzMethod;
typedef DotStarSpi10MhzMethod DotStarSpiMethod;
#endif

View File

@ -16,7 +16,6 @@
// limitations under the License.
#if defined(ARDUINO_ARCH_ESP32)
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include <string.h>
#include <stdio.h>
@ -47,15 +46,18 @@
#include "Esp32_i2s.h"
#include "esp32-hal.h"
#if ESP_IDF_VERSION_MAJOR<4
#if ESP_IDF_VERSION_MAJOR<=4
#define I2S_BASE_CLK (160000000L)
#endif
#define ESP32_REG(addr) (*((volatile uint32_t*)(0x3FF00000+(addr))))
#define I2S_DMA_QUEUE_SIZE 16
#define I2S_DMA_SILENCE_LEN 256 // bytes
#define I2S_DMA_BLOCK_COUNT_DEFAULT 16
// 24 bytes gives us enough time if we use single stage idle
// with the two stage idle we can use the minimum of 4 bytes
#define I2S_DMA_SILENCE_SIZE 4*1
#define I2S_DMA_SILENCE_BLOCK_COUNT 3 // two front, one back
#define I2S_DMA_QUEUE_COUNT 2
typedef struct i2s_dma_item_s {
uint32_t blocksize: 12; // datalen
@ -92,24 +94,29 @@ typedef struct {
size_t dma_count;
uint32_t dma_buf_len :12;
uint32_t unused :20;
volatile uint32_t is_sending_data;
} i2s_bus_t;
static uint8_t i2s_silence_buf[I2S_DMA_SILENCE_LEN];
// is_sending_data values
#define I2s_Is_Idle 0
#define I2s_Is_Pending 1
#define I2s_Is_Sending 2
static uint8_t i2s_silence_buf[I2S_DMA_SILENCE_SIZE] = { 0 };
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
// (I2S_NUM_MAX == 2)
static i2s_bus_t I2S[I2S_NUM_MAX] = {
{&I2S0, -1, -1, -1, -1, 0, NULL, NULL, i2s_silence_buf, I2S_DMA_SILENCE_LEN, NULL, I2S_DMA_QUEUE_SIZE, 0, 0},
{&I2S1, -1, -1, -1, -1, 0, NULL, NULL, i2s_silence_buf, I2S_DMA_SILENCE_LEN, NULL, I2S_DMA_QUEUE_SIZE, 0, 0}
{&I2S0, -1, -1, -1, -1, 0, NULL, NULL, i2s_silence_buf, I2S_DMA_SILENCE_SIZE, NULL, I2S_DMA_BLOCK_COUNT_DEFAULT, 0, 0, I2s_Is_Idle},
{&I2S1, -1, -1, -1, -1, 0, NULL, NULL, i2s_silence_buf, I2S_DMA_SILENCE_SIZE, NULL, I2S_DMA_BLOCK_COUNT_DEFAULT, 0, 0, I2s_Is_Idle}
};
#else
static i2s_bus_t I2S[I2S_NUM_MAX] = {
{&I2S0, -1, -1, -1, -1, 0, NULL, NULL, i2s_silence_buf, I2S_DMA_SILENCE_LEN, NULL, I2S_DMA_QUEUE_SIZE, 0, 0}
{&I2S0, -1, -1, -1, -1, 0, NULL, NULL, i2s_silence_buf, I2S_DMA_SILENCE_SIZE, NULL, I2S_DMA_BLOCK_COUNT_DEFAULT, 0, 0, I2s_Is_Idle}
};
#endif
void IRAM_ATTR i2sDmaISR(void* arg);
bool i2sInitDmaItems(uint8_t bus_num);
bool i2sInitDmaItems(uint8_t bus_num) {
if (bus_num >= I2S_NUM_MAX) {
@ -119,8 +126,10 @@ bool i2sInitDmaItems(uint8_t bus_num) {
return true;
}
size_t dmaCount = I2S[bus_num].dma_count;
if (I2S[bus_num].dma_items == NULL) {
I2S[bus_num].dma_items = (i2s_dma_item_t*)(malloc(I2S[bus_num].dma_count* sizeof(i2s_dma_item_t)));
I2S[bus_num].dma_items = (i2s_dma_item_t*)(malloc(dmaCount * sizeof(i2s_dma_item_t)));
if (I2S[bus_num].dma_items == NULL) {
log_e("MEM ERROR!");
return false;
@ -128,12 +137,15 @@ bool i2sInitDmaItems(uint8_t bus_num) {
}
int i, i2, a;
i2s_dma_item_t* item;
i2s_dma_item_t* item = NULL;
i2s_dma_item_t* itemPrev;
for(i=0; i<I2S[bus_num].dma_count; i++) {
i2 = (i+1) % I2S[bus_num].dma_count;
for(i=0; i< dmaCount; i++) {
itemPrev = item;
i2 = (i+1) % dmaCount;
item = &I2S[bus_num].dma_items[i];
item->eof = 1;
item->eof = 0;
item->owner = 1;
item->sub_sof = 0;
item->unused = 0;
@ -142,23 +154,12 @@ bool i2sInitDmaItems(uint8_t bus_num) {
item->datalen = I2S[bus_num].silence_len;
item->next = &I2S[bus_num].dma_items[i2];
item->free_ptr = NULL;
if (I2S[bus_num].dma_buf_len) {
item->buf = (uint8_t*)(malloc(I2S[bus_num].dma_buf_len));
if (item->buf == NULL) {
log_e("MEM ERROR!");
for(a=0; a<i; a++) {
free(I2S[bus_num].dma_items[i].buf);
}
free(I2S[bus_num].dma_items);
I2S[bus_num].dma_items = NULL;
return false;
}
} else {
item->buf = NULL;
}
}
itemPrev->eof = 1;
item->eof = 1;
I2S[bus_num].tx_queue = xQueueCreate(I2S[bus_num].dma_count, sizeof(i2s_dma_item_t*));
I2S[bus_num].tx_queue = xQueueCreate(I2S_DMA_QUEUE_COUNT, sizeof(i2s_dma_item_t*));
if (I2S[bus_num].tx_queue == NULL) {// memory error
log_e("MEM ERROR!");
free(I2S[bus_num].dma_items);
@ -168,14 +169,6 @@ bool i2sInitDmaItems(uint8_t bus_num) {
return true;
}
void i2sSetSilenceBuf(uint8_t bus_num, uint8_t* data, size_t len) {
if (bus_num >= I2S_NUM_MAX || !data || !len) {
return;
}
I2S[bus_num].silence_buf = data;
I2S[bus_num].silence_len = len;
}
esp_err_t i2sSetClock(uint8_t bus_num, uint8_t div_num, uint8_t div_b, uint8_t div_a, uint8_t bck, uint8_t bits) {
if (bus_num >= I2S_NUM_MAX || div_a > 63 || div_b > 63 || bck > 63) {
return ESP_FAIL;
@ -206,37 +199,6 @@ esp_err_t i2sSetClock(uint8_t bus_num, uint8_t div_num, uint8_t div_b, uint8_t d
return ESP_OK;
}
void i2sSetDac(uint8_t bus_num, bool right, bool left) {
if (bus_num >= I2S_NUM_MAX) {
return;
}
if (!right && !left) {
dac_output_disable(DAC_CHANNEL_1);
dac_output_disable(DAC_CHANNEL_2);
dac_i2s_disable();
I2S[bus_num].bus->conf2.lcd_en = 0;
I2S[bus_num].bus->conf.tx_right_first = 0;
I2S[bus_num].bus->conf2.camera_en = 0;
I2S[bus_num].bus->conf.tx_msb_shift = 1;// I2S signaling
return;
}
i2sSetPins(bus_num, -1, false);
I2S[bus_num].bus->conf2.lcd_en = 1;
I2S[bus_num].bus->conf.tx_right_first = 0;
I2S[bus_num].bus->conf2.camera_en = 0;
I2S[bus_num].bus->conf.tx_msb_shift = 0;
dac_i2s_enable();
if (right) {// DAC1, right channel, GPIO25
dac_output_enable(DAC_CHANNEL_1);
}
if (left) { // DAC2, left channel, GPIO26
dac_output_enable(DAC_CHANNEL_2);
}
}
void i2sSetPins(uint8_t bus_num, int8_t out, bool invert) {
if (bus_num >= I2S_NUM_MAX) {
return;
@ -275,15 +237,22 @@ bool i2sWriteDone(uint8_t bus_num) {
if (bus_num >= I2S_NUM_MAX) {
return false;
}
return (I2S[bus_num].dma_items[I2S[bus_num].dma_count - 1].data == I2S[bus_num].silence_buf);
return (I2S[bus_num].is_sending_data == I2s_Is_Idle);
}
void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2s_tx_chan_mod_t chan_mod, i2s_tx_fifo_mod_t fifo_mod, size_t dma_count, size_t dma_len) {
void i2sInit(uint8_t bus_num,
uint32_t bits_per_sample,
uint32_t sample_rate,
i2s_tx_chan_mod_t chan_mod,
i2s_tx_fifo_mod_t fifo_mod,
size_t dma_count,
size_t dma_len) {
if (bus_num >= I2S_NUM_MAX) {
return;
}
I2S[bus_num].dma_count = dma_count;
I2S[bus_num].dma_count = dma_count + I2S_DMA_SILENCE_BLOCK_COUNT; // an extra two for looping silence
I2S[bus_num].dma_buf_len = dma_len & 0xFFF;
if (!i2sInitDmaItems(bus_num)) {
@ -332,8 +301,10 @@ void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2
lc_conf.out_eof_mode = 1;
i2s->lc_conf.val = lc_conf.val;
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
i2s->pdm_conf.pcm2pdm_conv_en = 0;
i2s->pdm_conf.pdm2pcm_conv_en = 0;
#endif
// SET_PERI_REG_BITS(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, 0x1, RTC_CNTL_SOC_CLK_SEL_S);
typeof(i2s->conf_chan) conf_chan;
@ -361,8 +332,10 @@ void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2
i2s->fifo_conf.tx_fifo_mod_force_en = 1;
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
i2s->pdm_conf.rx_pdm_en = 0;
i2s->pdm_conf.tx_pdm_en = 0;
#endif
i2sSetSampleRate(bus_num, sample_rate, bits_per_sample);
@ -443,57 +416,77 @@ esp_err_t i2sSetSampleRate(uint8_t bus_num, uint32_t rate, uint8_t bits) {
return ESP_OK;
}
void IRAM_ATTR i2sDmaISR(void* arg)
{
i2s_dma_item_t* dummy = NULL;
i2s_bus_t* dev = (i2s_bus_t*)(arg);
portBASE_TYPE hpTaskAwoken = 0;
if (dev->bus->int_st.out_eof) {
i2s_dma_item_t* item = (i2s_dma_item_t*)(dev->bus->out_eof_des_addr);
item->data = dev->silence_buf;
item->blocksize = dev->silence_len;
item->datalen = dev->silence_len;
if (xQueueIsQueueFullFromISR(dev->tx_queue) == pdTRUE) {
xQueueReceiveFromISR(dev->tx_queue, &dummy, &hpTaskAwoken);
if (dev->bus->int_st.out_eof)
{
// i2s_dma_item_t* item = (i2s_dma_item_t*)(dev->bus->out_eof_des_addr);
if (dev->is_sending_data == I2s_Is_Pending)
{
dev->is_sending_data = I2s_Is_Idle;
}
xQueueSendFromISR(dev->tx_queue, (void*)&item, &hpTaskAwoken);
else if (dev->is_sending_data == I2s_Is_Sending)
{
// loop the silent items
i2s_dma_item_t* itemSilence = &dev->dma_items[1];
itemSilence->next = &dev->dma_items[0];
dev->is_sending_data = I2s_Is_Pending;
}
}
dev->bus->int_clr.val = dev->bus->int_st.val;
if (hpTaskAwoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
size_t i2sWrite(uint8_t bus_num, uint8_t* data, size_t len, bool copy, bool free_when_sent) {
if (bus_num >= I2S_NUM_MAX || !I2S[bus_num].tx_queue) {
return 0;
}
size_t index = 0;
size_t toSend = len;
size_t limit = I2S_DMA_MAX_DATA_LEN;
i2s_dma_item_t* item = NULL;
size_t blockSize = len;
while (len) {
toSend = len;
if (toSend > limit) {
toSend = limit;
}
i2s_dma_item_t* itemPrev = NULL;
i2s_dma_item_t* item = &I2S[bus_num].dma_items[0];
size_t dataLeft = len;
uint8_t* pos = data;
if (xQueueReceive(I2S[bus_num].tx_queue, &item, portMAX_DELAY) == pdFALSE) {
log_e("xQueueReceive failed\n");
break;
// skip front two silent items
item += 2;
while (dataLeft) {
blockSize = dataLeft;
if (blockSize > I2S_DMA_MAX_DATA_LEN) {
blockSize = I2S_DMA_MAX_DATA_LEN;
}
dataLeft -= blockSize;
// data is constant. no need to copy
item->data = data + index;
item->blocksize = toSend;
item->datalen = toSend;
item->data = pos;
item->blocksize = blockSize;
item->datalen = blockSize;
len -= toSend;
index += toSend;
itemPrev = item;
item++;
pos += blockSize;
}
return index;
// reset silence item to not loop
item = &I2S[bus_num].dma_items[1];
item->next = &I2S[bus_num].dma_items[2];
I2S[bus_num].is_sending_data = I2s_Is_Sending;
xQueueReset(I2S[bus_num].tx_queue);
xQueueSend(I2S[bus_num].tx_queue, (void*)&I2S[bus_num].dma_items[0], 10);
return len;
}
#endif // CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#endif

View File

@ -18,16 +18,19 @@ typedef enum {
I2S_FIFO_16BIT_DUAL, I2S_FIFO_16BIT_SINGLE, I2S_FIFO_32BIT_DUAL, I2S_FIFO_32BIT_SINGLE
} i2s_tx_fifo_mod_t;
void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2s_tx_chan_mod_t chan_mod, i2s_tx_fifo_mod_t fifo_mod, size_t dma_count, size_t dma_len);
void i2sInit(uint8_t bus_num,
uint32_t bits_per_sample,
uint32_t sample_rate,
i2s_tx_chan_mod_t chan_mod,
i2s_tx_fifo_mod_t fifo_mod,
size_t dma_count,
size_t dma_len);
void i2sSetPins(uint8_t bus_num, int8_t out, bool invert);
void i2sSetDac(uint8_t bus_num, bool right, bool left);
esp_err_t i2sSetClock(uint8_t bus_num, uint8_t div_num, uint8_t div_b, uint8_t div_a, uint8_t bck, uint8_t bits_per_sample);
esp_err_t i2sSetSampleRate(uint8_t bus_num, uint32_t sample_rate, uint8_t bits_per_sample);
void i2sSetSilenceBuf(uint8_t bus_num, uint8_t* data, size_t len);
size_t i2sWrite(uint8_t bus_num, uint8_t* data, size_t len, bool copy, bool free_when_sent);
bool i2sWriteDone(uint8_t bus_num);

View File

@ -25,18 +25,13 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#include "RgbColor.h"
#include "Rgb48Color.h"
#include "HsbColor.h"
HsbColor::HsbColor(const RgbColor& color)
void HsbColor::_RgbToHsb(float r, float g, float b, HsbColor* color)
{
// convert colors to float between (0.0 - 1.0)
float r = color.R / 255.0f;
float g = color.G / 255.0f;
float b = color.B / 255.0f;
float max = (r > g && r > b) ? r : (g > b) ? g : b;
float min = (r < g && r < b) ? r : (g < b) ? g : b;
float min = (r < g&& r < b) ? r : (g < b) ? g : b;
float d = max - min;
@ -62,7 +57,27 @@ HsbColor::HsbColor(const RgbColor& color)
}
H = h;
S = s;
B = v;
color->H = h;
color->S = s;
color->B = v;
}
HsbColor::HsbColor(const RgbColor& color)
{
// convert colors to float between (0.0 - 1.0)
float r = color.R / 255.0f;
float g = color.G / 255.0f;
float b = color.B / 255.0f;
_RgbToHsb(r, g, b, this);
}
HsbColor::HsbColor(const Rgb48Color& color)
{
// convert colors to float between (0.0 - 1.0)
float r = color.R / 65535.0f;
float g = color.G / 65535.0f;
float b = color.B / 65535.0f;
_RgbToHsb(r, g, b, this);
}

View File

@ -48,6 +48,11 @@ struct HsbColor
// ------------------------------------------------------------------------
HsbColor(const RgbColor& color);
// ------------------------------------------------------------------------
// Construct a HsbColor using Rgb48Color
// ------------------------------------------------------------------------
HsbColor(const Rgb48Color& color);
// ------------------------------------------------------------------------
// Construct a HsbColor that will have its values set in latter operations
// CAUTION: The H,S,B members are not initialized and may not be consistent
@ -109,5 +114,8 @@ struct HsbColor
float H;
float S;
float B;
private:
static void _RgbToHsb(float r, float g, float b, HsbColor* color);
};

View File

@ -26,16 +26,11 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#include "RgbColor.h"
#include "Rgb48Color.h"
#include "HslColor.h"
HslColor::HslColor(const RgbColor& color)
void HslColor::_RgbToHsl(float r, float g, float b, HslColor* color)
{
// convert colors to float between (0.0 - 1.0)
float r = color.R / 255.0f;
float g = color.G / 255.0f;
float b = color.B / 255.0f;
float max = (r > g && r > b) ? r : (g > b) ? g : b;
float min = (r < g && r < b) ? r : (g < b) ? g : b;
@ -66,7 +61,27 @@ HslColor::HslColor(const RgbColor& color)
h /= 6.0f;
}
H = h;
S = s;
L = l;
color->H = h;
color->S = s;
color->L = l;
}
HslColor::HslColor(const RgbColor& color)
{
// convert colors to float between (0.0 - 1.0)
float r = color.R / 255.0f;
float g = color.G / 255.0f;
float b = color.B / 255.0f;
_RgbToHsl(r, g, b, this);
}
HslColor::HslColor(const Rgb48Color& color)
{
// convert colors to float between (0.0 - 1.0)
float r = color.R / 65535.0f;
float g = color.G / 65535.0f;
float b = color.B / 65535.0f;
_RgbToHsl(r, g, b, this);
}

View File

@ -49,6 +49,11 @@ struct HslColor
// ------------------------------------------------------------------------
HslColor(const RgbColor& color);
// ------------------------------------------------------------------------
// Construct a HslColor using Rgb48Color
// ------------------------------------------------------------------------
HslColor(const Rgb48Color& color);
// ------------------------------------------------------------------------
// Construct a HslColor that will have its values set in latter operations
// CAUTION: The H,S,L members are not initialized and may not be consistent
@ -109,5 +114,9 @@ struct HslColor
float H;
float S;
float L;
private:
static void _RgbToHsl(float r, float g, float b, HslColor* color);
};

View File

@ -0,0 +1,301 @@
/*-------------------------------------------------------------------------
Lpd6803ColorFeatures provides feature classes to describe color order and
color depth for NeoPixelBus template class when used with DotStar like chips
Written by Michael C. Miller.
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
class Lpd68033ElementsNoSettings
{
public:
typedef NeoNoSettings SettingsObject;
static const size_t SettingsSize = 0;
static void applySettings(uint8_t*, const SettingsObject&)
{
}
static uint8_t* pixels(uint8_t* pData)
{
return pData;
}
static const uint8_t* pixels(const uint8_t* pData)
{
return pData;
}
};
class Lpd68033Elements : public Lpd68033ElementsNoSettings
{
public:
static const size_t PixelSize = 2; // 1 bit + 555 encoded elements
static uint8_t* getPixelAddress(uint8_t* pPixels, uint16_t indexPixel)
{
return pPixels + indexPixel * PixelSize;
}
static const uint8_t* getPixelAddress(const uint8_t* pPixels, uint16_t indexPixel)
{
return pPixels + indexPixel * PixelSize;
}
static void replicatePixel(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count)
{
uint8_t* pEnd = pPixelDest + (count * PixelSize);
while (pPixelDest < pEnd)
{
*pPixelDest++ = pPixelSrc[0];
*pPixelDest++ = pPixelSrc[1];
}
}
static void movePixelsInc(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count)
{
uint8_t* pEnd = pPixelDest + (count * PixelSize);
while (pPixelDest < pEnd)
{
*pPixelDest++ = *pPixelSrc++;
*pPixelDest++ = *pPixelSrc++;
}
}
static void movePixelsInc_P(uint8_t* pPixelDest, PGM_VOID_P pPixelSrc, uint16_t count)
{
uint8_t* pEnd = pPixelDest + (count * PixelSize);
const uint8_t* pSrc = (const uint8_t*)pPixelSrc;
while (pPixelDest < pEnd)
{
*pPixelDest++ = pgm_read_byte(pSrc++);
*pPixelDest++ = pgm_read_byte(pSrc++);
}
}
static void movePixelsDec(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count)
{
uint8_t* pDestBack = pPixelDest + (count * PixelSize);
const uint8_t* pSrcBack = pPixelSrc + (count * PixelSize);
while (pDestBack > pPixelDest)
{
*--pDestBack = *--pSrcBack;
*--pDestBack = *--pSrcBack;
}
}
typedef RgbColor ColorObject;
protected:
static void encodePixel(uint8_t c1, uint8_t c2, uint8_t c3, uint16_t* color555)
{
*color555 = (0x8000 |
((c1 & 0xf8) << 7) |
((c2 & 0xf8) << 2) |
((c3 & 0xf8) >> 3));
}
static void decodePixel(uint16_t color555, uint8_t* c1, uint8_t* c2, uint8_t* c3)
{
*c1 = (color555 >> 7) & 0xf8;
*c2 = (color555 >> 2) & 0xf8;
*c3 = (color555 << 3) & 0xf8;
}
};
class Lpd6803BrgFeature : public Lpd68033Elements
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
{
uint8_t* p = getPixelAddress(pPixels, indexPixel);
uint16_t color555;
encodePixel(color.B, color.R, color.G, &color555);
*p++ = color555 >> 8;
*p = color555 & 0xff;
}
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
uint16_t color555;
color555 = ((*p++) << 8);
color555 |= (*p);
decodePixel(color555, &color.B, &color.R, &color.G);
return color;
}
static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel);
uint16_t color555;
color555 = (pgm_read_byte(p++) << 8);
color555 |= pgm_read_byte(p);
decodePixel(color555, &color.B, &color.R, &color.G);
return color;
}
};
class Lpd6803GrbFeature : public Lpd68033Elements
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
{
uint8_t* p = getPixelAddress(pPixels, indexPixel);
uint16_t color555;
encodePixel(color.G, color.R, color.B, &color555);
*p++ = color555 >> 8;
*p = color555 & 0xff;
}
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
uint16_t color555;
color555 = ((*p++) << 8);
color555 |= (*p);
decodePixel(color555, &color.G, &color.R, &color.B);
return color;
}
static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel);
uint16_t color555;
color555 = (pgm_read_byte(p++) << 8);
color555 |= pgm_read_byte(p);
decodePixel(color555, &color.G, &color.R, &color.B);
return color;
}
};
class Lpd6803GbrFeature : public Lpd68033Elements
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
{
uint8_t* p = getPixelAddress(pPixels, indexPixel);
uint16_t color555;
encodePixel(color.G, color.B, color.R, &color555);
*p++ = color555 >> 8;
*p = color555 & 0xff;
}
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
uint16_t color555;
color555 = ((*p++) << 8);
color555 |= (*p);
decodePixel(color555, &color.G, &color.B, &color.R);
return color;
}
static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel);
uint16_t color555;
color555 = (pgm_read_byte(p++) << 8);
color555 |= pgm_read_byte(p);
decodePixel(color555, &color.G, &color.B, &color.R);
return color;
}
};
class Lpd6803RgbFeature : public Lpd68033Elements
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
{
uint8_t* p = getPixelAddress(pPixels, indexPixel);
uint16_t color555;
encodePixel(color.R, color.G, color.B, &color555);
*p++ = color555 >> 8;
*p = color555 & 0xff;
}
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
uint16_t color555;
color555 = ((*p++) << 8);
color555 |= (*p);
decodePixel(color555, &color.R, &color.G, &color.B);
return color;
}
static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel);
uint16_t color555;
color555 = (pgm_read_byte(p++) << 8);
color555 |= pgm_read_byte(p);
decodePixel(color555, &color.R, &color.G, &color.B);
return color;
}
};

View File

@ -0,0 +1,132 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for LPD6803 using general Pins
Written by Michael C. Miller.
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
// must also check for arm due to Teensy incorrectly having ARDUINO_ARCH_AVR set
#if defined(ARDUINO_ARCH_AVR) && !defined(__arm__)
#include "TwoWireBitBangImpleAvr.h"
#else
#include "TwoWireBitBangImple.h"
#endif
template<typename T_TWOWIRE> class Lpd6803MethodBase
{
public:
Lpd6803MethodBase(uint8_t pinClock, uint8_t pinData, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize),
_sizeFrame((pixelCount + 7) / 8), // bit for every pixel at least
_wire(pinClock, pinData)
{
_data = static_cast<uint8_t*>(malloc(_sizeData));
// data cleared later in Begin()
}
#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
Lpd6803MethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
Lpd6803MethodBase(SCK, MOSI, pixelCount, elementSize, settingsSize)
{
}
#endif
~Lpd6803MethodBase()
{
free(_data);
}
bool IsReadyToUpdate() const
{
return true; // dot stars don't have a required delay
}
#if defined(ARDUINO_ARCH_ESP32)
void Initialize(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
{
_wire.begin(sck, miso, mosi, ss);
}
#endif
void Initialize()
{
_wire.begin();
}
void Update(bool)
{
const uint8_t startFrame[4] = { 0x00 };
_wire.beginTransaction();
// start frame
_wire.transmitBytes(startFrame, sizeof(startFrame));
// data
_wire.transmitBytes(_data, _sizeData);
// end frame
// one bit for every pixel with no less than 1 byte
for (size_t frameByte = 0; frameByte < _sizeFrame; frameByte++)
{
_wire.transmitByte(0x00);
}
_wire.endTransaction();
}
uint8_t* getData() const
{
return _data;
};
size_t getDataSize() const
{
return _sizeData;
};
private:
const size_t _sizeData; // Size of '_data' buffer below
const size_t _sizeFrame;
T_TWOWIRE _wire;
uint8_t* _data; // Holds LED color values
};
typedef Lpd6803MethodBase<TwoWireBitBangImple> Lpd6803Method;
#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
#include "TwoWireSpiImple.h"
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> Lpd6803Spi20MhzMethod;
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> Lpd6803Spi10MhzMethod;
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> Lpd6803Spi2MhzMethod;
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> Lpd6803Spi1MhzMethod;
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed500Khz>> Lpd6803Spi500KhzMethod;
typedef Lpd6803Spi10MhzMethod Lpd6803SpiMethod;
#endif

View File

@ -43,7 +43,7 @@ public:
_wire(pinClock, pinData)
{
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
// data cleared later in Begin()
}
#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
@ -123,6 +123,8 @@ typedef Lpd8806MethodBase<TwoWireBitBangImple> Lpd8806Method;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> Lpd8806Spi20MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> Lpd8806Spi10MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> Lpd8806Spi2MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> Lpd8806Spi1MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed500Khz>> Lpd8806Spi500KhzMethod;
typedef Lpd8806Spi10MhzMethod Lpd8806SpiMethod;
#endif

View File

@ -42,7 +42,7 @@ public:
pinMode(pin, OUTPUT);
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
// data cleared later in Begin()
}
~NeoArmMethodBase()
@ -334,7 +334,7 @@ typedef NeoArmMethodBase<NeoArmMk26z64SpeedWs2812x> NeoArmWs2812xMethod;
typedef NeoArmMethodBase<NeoArmMk26z64SpeedSk6812> NeoArmSk6812Method;
typedef NeoArmMethodBase<NeoArmMk26z64SpeedTm1814> NeoArmTm1814InvertedMethod;
typedef NeoArmMethodBase<NeoArmMk26z64Speed800Kbps> NeoArm800KbpsMethod;
typedef NeoArm800KbpsMethod NeoArmApa106Method
typedef NeoArm800KbpsMethod NeoArmApa106Method;
#else
#error "Teensy-LC: Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz"

View File

@ -127,7 +127,7 @@ public:
pinMode(pin, OUTPUT);
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
// data cleared later in Begin()
_port = portOutputRegister(digitalPinToPort(pin));
_pinMask = digitalPinToBitMask(pin);

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

@ -87,15 +87,32 @@ public:
class NeoEsp32I2sBusZero
{
public:
NeoEsp32I2sBusZero() {};
const static uint8_t I2sBusNumber = 0;
};
class NeoEsp32I2sBusOne
{
public:
NeoEsp32I2sBusOne() {};
const static uint8_t I2sBusNumber = 1;
};
// dynamic channel support
class NeoEsp32I2sBusN
{
public:
NeoEsp32I2sBusN(NeoBusChannel channel) :
I2sBusNumber(static_cast<uint8_t>(channel))
{
}
NeoEsp32I2sBusN() = delete; // no default constructor
const uint8_t I2sBusNumber;
};
class NeoEsp32I2sNotInverted
{
public:
@ -115,24 +132,15 @@ public:
_sizeData(pixelCount * elementSize + settingsSize),
_pin(pin)
{
uint16_t dmaSettingsSize = c_dmaBytesPerPixelBytes * settingsSize;
uint16_t dmaPixelSize = c_dmaBytesPerPixelBytes * elementSize;
uint16_t resetSize = c_dmaBytesPerPixelBytes * T_SPEED::ResetTimeUs / T_SPEED::ByteSendTimeUs;
_i2sBufferSize = pixelCount * dmaPixelSize + dmaSettingsSize + resetSize;
// must have a 4 byte aligned buffer for i2s
uint32_t alignment = _i2sBufferSize % 4;
if (alignment)
{
_i2sBufferSize += 4 - alignment;
construct(pixelCount, elementSize, settingsSize);
}
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0x00, _sizeData);
_i2sBuffer = static_cast<uint8_t*>(malloc(_i2sBufferSize));
memset(_i2sBuffer, 0x00, _i2sBufferSize);
NeoEsp32I2sMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) :
_sizeData(pixelCount * elementSize + settingsSize),
_pin(pin),
_bus(channel)
{
construct(pixelCount, elementSize, settingsSize);
}
~NeoEsp32I2sMethodBase()
@ -150,14 +158,21 @@ public:
bool IsReadyToUpdate() const
{
return (i2sWriteDone(T_BUS::I2sBusNumber));
return (i2sWriteDone(_bus.I2sBusNumber));
}
void Initialize()
{
size_t dmaCount = (_i2sBufferSize + I2S_DMA_MAX_DATA_LEN - 1) / I2S_DMA_MAX_DATA_LEN;
i2sInit(T_BUS::I2sBusNumber, 16, T_SPEED::I2sSampleRate, I2S_CHAN_STEREO, I2S_FIFO_16BIT_DUAL, dmaCount, 0);
i2sSetPins(T_BUS::I2sBusNumber, _pin, T_INVERT::Inverted);
size_t dmaBlockCount = (_i2sBufferSize + I2S_DMA_MAX_DATA_LEN - 1) / I2S_DMA_MAX_DATA_LEN;
i2sInit(_bus.I2sBusNumber,
16,
T_SPEED::I2sSampleRate,
I2S_CHAN_STEREO,
I2S_FIFO_16BIT_DUAL,
dmaBlockCount,
0);
i2sSetPins(_bus.I2sBusNumber, _pin, T_INVERT::Inverted);
}
void Update(bool)
@ -170,7 +185,7 @@ public:
FillBuffers();
i2sWrite(T_BUS::I2sBusNumber, _i2sBuffer, _i2sBufferSize, false, false);
i2sWrite(_bus.I2sBusNumber, _i2sBuffer, _i2sBufferSize, false, false);
}
uint8_t* getData() const
@ -186,12 +201,39 @@ public:
private:
const size_t _sizeData; // Size of '_data' buffer
const uint8_t _pin; // output pin number
const T_BUS _bus; // holds instance for multi bus support
uint8_t* _data; // Holds LED color values
uint32_t _i2sBufferSize; // total size of _i2sBuffer
uint8_t* _i2sBuffer; // holds the DMA buffer that is referenced by _i2sBufDesc
void construct(uint16_t pixelCount, size_t elementSize, size_t settingsSize)
{
ESP_ERROR_CHECK(pixelCount >= 2 ? ESP_OK : ESP_ERR_INVALID_ARG);
uint16_t dmaSettingsSize = c_dmaBytesPerPixelBytes * settingsSize;
uint16_t dmaPixelSize = c_dmaBytesPerPixelBytes * elementSize;
uint16_t resetSize = c_dmaBytesPerPixelBytes * T_SPEED::ResetTimeUs / T_SPEED::ByteSendTimeUs;
_i2sBufferSize = pixelCount * dmaPixelSize + dmaSettingsSize + resetSize;
// must have a 4 byte aligned buffer for i2s
uint32_t alignment = _i2sBufferSize % 4;
if (alignment)
{
_i2sBufferSize += 4 - alignment;
}
_data = static_cast<uint8_t*>(malloc(_sizeData));
// data cleared later in Begin()
_i2sBuffer = static_cast<uint8_t*>(malloc(_i2sBufferSize));
// no need to initialize all of it, but since it contains
// "reset" bits that don't latter get overwritten we just clear it all
memset(_i2sBuffer, 0x00, _i2sBufferSize);
}
void FillBuffers()
{
const uint16_t bitpatterns[16] =
@ -244,6 +286,21 @@ typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusOne, NeoEsp
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1400KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Apa106InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNWs2812xMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNSk6812Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNTm1814Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sN800KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sN400KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNApa106Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNWs2812xInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNSk6812InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNTm1814InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sN800KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sN400KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNApa106InvertedMethod;
#endif
/* due to a core issue where requests to send aren't consistent, I2s is no longer the default

View File

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

View File

@ -201,8 +201,8 @@ public:
class NeoEsp32RmtSpeedApa106 : public NeoEsp32RmtSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(400, 1250);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(1250, 400);
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(350, 1350);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(1350, 350);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(50000); // 50us
static void IRAM_ATTR Translate(const void* src,
@ -307,8 +307,8 @@ public:
class NeoEsp32RmtInvertedSpeedApa106 : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(400, 1250);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(1250, 400);
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(350, 1350);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(1350, 350);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(50000); // 50us
static void IRAM_ATTR Translate(const void* src,
@ -322,24 +322,32 @@ public:
class NeoEsp32RmtChannel0
{
public:
NeoEsp32RmtChannel0() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_0;
};
class NeoEsp32RmtChannel1
{
public:
NeoEsp32RmtChannel1() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_1;
};
class NeoEsp32RmtChannel2
{
public:
NeoEsp32RmtChannel2() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_2;
};
class NeoEsp32RmtChannel3
{
public:
NeoEsp32RmtChannel3() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_3;
};
@ -348,29 +356,50 @@ public:
class NeoEsp32RmtChannel4
{
public:
NeoEsp32RmtChannel4() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_4;
};
class NeoEsp32RmtChannel5
{
public:
NeoEsp32RmtChannel5() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_5;
};
class NeoEsp32RmtChannel6
{
public:
NeoEsp32RmtChannel6() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_6;
};
class NeoEsp32RmtChannel7
{
public:
NeoEsp32RmtChannel7() {};
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_7;
};
#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
{
public:
@ -378,20 +407,24 @@ public:
_sizeData(pixelCount * elementSize + settingsSize),
_pin(pin)
{
_dataEditing = static_cast<uint8_t*>(malloc(_sizeData));
memset(_dataEditing, 0x00, _sizeData);
construct();
}
_dataSending = static_cast<uint8_t*>(malloc(_sizeData));
// no need to initialize it, it gets overwritten on every send
NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) :
_sizeData(pixelCount* elementSize + settingsSize),
_pin(pin),
_channel(channel)
{
construct();
}
~NeoEsp32RmtMethodBase()
{
// wait until the last send finishes before destructing everything
// 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(_dataSending);
@ -400,7 +433,7 @@ public:
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()
@ -408,7 +441,7 @@ public:
rmt_config_t config;
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.mem_block_num = 1;
config.tx_config.loop_en = false;
@ -422,8 +455,8 @@ public:
config.clk_div = T_SPEED::RmtClockDivider;
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_translator_init(T_CHANNEL::RmtChannelNumber, T_SPEED::Translate));
ESP_ERROR_CHECK(rmt_driver_install(_channel.RmtChannelNumber, 0, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1));
ESP_ERROR_CHECK(rmt_translator_init(_channel.RmtChannelNumber, T_SPEED::Translate));
}
void Update(bool maintainBufferConsistency)
@ -431,10 +464,10 @@ public:
// wait for not actively sending data
// this will time out at 10 seconds, an arbitrarily long period of time
// 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
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)
{
@ -462,13 +495,32 @@ public:
private:
const size_t _sizeData; // Size of '_data*' buffers
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
uint8_t* _dataEditing; // exposed for get and set
uint8_t* _dataSending; // used for async send using RMT
void construct()
{
_dataEditing = static_cast<uint8_t*>(malloc(_sizeData));
// data cleared later in Begin()
_dataSending = static_cast<uint8_t*>(malloc(_sizeData));
// no need to initialize it, it gets overwritten on every send
}
};
// 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<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812Method;
@ -539,6 +591,14 @@ typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel7> NeoE
#endif
// 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<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812InvertedMethod;

View File

@ -226,10 +226,10 @@ public:
_i2sBufferSize = pixelCount * dmaPixelSize + dmaSettingsSize;
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0x00, _sizeData);
// data cleared later in Begin()
_i2sBuffer = static_cast<uint8_t*>(malloc(_i2sBufferSize));
memset(_i2sBuffer, T_SPEED::Level, _i2sBufferSize);
// no need to initialize it, it gets overwritten on every send
// _i2sBuffer[0] = 0b11101000; // debug, 1 bit then 0 bit

View File

@ -150,7 +150,7 @@ protected:
_sizeData(pixelCount * elementSize + settingsSize)
{
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0x00, _sizeData);
// data cleared later in Begin()
}
~NeoEsp8266UartBase()

View File

@ -71,6 +71,14 @@ public:
const static uint32_t Period = (F_CPU / 400000 - CYCLES_LOOPTEST);
};
class NeoEspSpeedApa106
{
public:
const static uint32_t T0H = (F_CPU / 2857143 - CYCLES_LOOPTEST); // 0.35us
const static uint32_t T1H = (F_CPU / 740741 - CYCLES_LOOPTEST); // 1.35
const static uint32_t Period = (F_CPU / 606061 - CYCLES_LOOPTEST); // 1.65us
};
class NeoEspPinset
{
public:
@ -218,6 +226,11 @@ public:
static const uint32_t ResetTimeUs = 50;
};
class NeoEspBitBangSpeedApa106 : public NeoEspBitBangBase<NeoEspSpeedApa106, NeoEspPinset>
{
public:
static const uint32_t ResetTimeUs = 50;
};
class NeoEspBitBangInvertedSpeedWs2811 : public NeoEspBitBangBase<NeoEspSpeedWs2811, NeoEspPinsetInverted>
{
@ -256,6 +269,12 @@ public:
static const uint32_t ResetTimeUs = 50;
};
class NeoEspBitBangInvertedSpeedApa106 : public NeoEspBitBangBase<NeoEspSpeedApa106, NeoEspPinsetInverted>
{
public:
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEED, typename T_PINSET> class NeoEspBitBangMethodBase
{
public:
@ -266,7 +285,7 @@ public:
pinMode(pin, OUTPUT);
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
// data cleared later in Begin()
}
~NeoEspBitBangMethodBase()
@ -352,11 +371,11 @@ typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812, NeoEspPinset> NeoEsp32
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedTm1814, NeoEspPinsetInverted> NeoEsp32BitBangTm1814Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps, NeoEspPinset> NeoEsp32BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps, NeoEspPinset> NeoEsp32BitBang400KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedApa106, NeoEspPinset> NeoEsp32BitBangApa106Method;
typedef NeoEsp32BitBangWs2812xMethod NeoEsp32BitBangWs2813Method;
typedef NeoEsp32BitBang800KbpsMethod NeoEsp32BitBangWs2812Method;
typedef NeoEsp32BitBangSk6812Method NeoEsp32BitBangLc8812Method;
typedef NeoEsp32BitBang400KbpsMethod NeoEsp32BitBangApa106Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2811, NeoEspPinsetInverted> NeoEsp32BitBangWs2811InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2812x, NeoEspPinsetInverted> NeoEsp32BitBangWs2812xInvertedMethod;
@ -364,11 +383,11 @@ typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedSk6812, NeoEspPinsetIn
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedTm1814, NeoEspPinset> NeoEsp32BitBangTm1814InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed800Kbps, NeoEspPinsetInverted> NeoEsp32BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed400Kbps, NeoEspPinsetInverted> NeoEsp32BitBang400KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedApa106, NeoEspPinsetInverted> NeoEsp32BitBangApa106InvertedMethod;
typedef NeoEsp32BitBangWs2812xInvertedMethod NeoEsp32BitBangWs2813InvertedMethod;
typedef NeoEsp32BitBang800KbpsInvertedMethod NeoEsp32BitBangWs2812InvertedMethod;
typedef NeoEsp32BitBangSk6812InvertedMethod NeoEsp32BitBangLc8812InvertedMethod;
typedef NeoEsp32BitBang400KbpsInvertedMethod NeoEsp32BitBangApa106InvertedMethod;
#else
@ -378,11 +397,11 @@ typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812, NeoEspPinset> NeoEsp82
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedTm1814, NeoEspPinsetInverted> NeoEsp8266BitBangTm1814Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps, NeoEspPinset> NeoEsp8266BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps, NeoEspPinset> NeoEsp8266BitBang400KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedApa106, NeoEspPinset> NeoEsp8266BitBangApa106Method;
typedef NeoEsp8266BitBangWs2812xMethod NeoEsp8266BitBangWs2813Method;
typedef NeoEsp8266BitBang800KbpsMethod NeoEsp8266BitBangWs2812Method;
typedef NeoEsp8266BitBangSk6812Method NeoEsp8266BitBangLc8812Method;
typedef NeoEsp8266BitBang400KbpsMethod NeoEsp8266BitBangApa106Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2811, NeoEspPinsetInverted> NeoEsp8266BitBangWs2811InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2812x, NeoEspPinsetInverted> NeoEsp8266BitBangWs2812xInvertedMethod;
@ -390,11 +409,12 @@ typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedSk6812, NeoEspPinsetIn
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedTm1814, NeoEspPinset> NeoEsp8266BitBangTm1814InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed800Kbps, NeoEspPinsetInverted> NeoEsp8266BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed400Kbps, NeoEspPinsetInverted> NeoEsp8266BitBang400KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedApa106, NeoEspPinsetInverted> NeoEsp8266BitBangApa106InvertedMethod;
typedef NeoEsp8266BitBangWs2812xInvertedMethod NeoEsp8266BitBangWs2813InvertedMethod;
typedef NeoEsp8266BitBang800KbpsInvertedMethod NeoEsp8266BitBangWs2812InvertedMethod;
typedef NeoEsp8266BitBangSk6812InvertedMethod NeoEsp8266BitBangLc8812InvertedMethod;
typedef NeoEsp8266BitBang400KbpsInvertedMethod NeoEsp8266BitBangApa106InvertedMethod;
#endif
// ESP bitbang doesn't have defaults and should avoided except for testing

View File

@ -102,12 +102,13 @@ public:
const static PinStatus IdleLevel = LOW;
};
// count 1 = 0.0625us, so max count (32768) is 2048us
class NeoNrf52xPwmSpeedApa106
{
public:
const static uint32_t CountTop = 26UL; // 1.65us
const static nrf_pwm_values_common_t Bit0 = 6 | 0x8000; // ~0.4us
const static nrf_pwm_values_common_t Bit1 = 20 | 0x8000; // ~1.25us
const static uint32_t CountTop = 26UL; // ~1.525us (target is 1.65us)
const static nrf_pwm_values_common_t Bit0 = 6 | 0x8000; // ~0.375us (target is 0.35)
const static nrf_pwm_values_common_t Bit1 = 21 | 0x8000; // ~1.3125us (target is 1.350)
const static nrf_pwm_values_common_t BitReset = 0x8000; // LOW
const static uint32_t CountReset = 40; // 50us / 1.25us pulse width
const static PinStatus IdleLevel = LOW;
@ -182,9 +183,9 @@ public:
class NeoNrf52xPwmInvertedSpeedApa106
{
public:
const static uint32_t CountTop = 26UL; // 1.65us
const static nrf_pwm_values_common_t Bit0 = 6; // ~0.4us
const static nrf_pwm_values_common_t Bit1 = 20; // ~1.25us
const static uint32_t CountTop = 26UL; // ~1.525us (target is 1.65us)
const static nrf_pwm_values_common_t Bit0 = 6; // ~0.375us (target is 0.35)
const static nrf_pwm_values_common_t Bit1 = 21; // ~1.3125us (target is 1.350)
const static nrf_pwm_values_common_t BitReset = 0x0000; // HIGH
const static uint32_t CountReset = 40; // 50us / 1.25us pulse width
const static PinStatus IdleLevel = HIGH;
@ -228,6 +229,34 @@ public:
};
#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
{
public:
@ -235,13 +264,15 @@ public:
_sizeData(pixelCount * elementSize + settingsSize),
_pin(pin)
{
pinMode(pin, OUTPUT);
construct();
}
_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));
NeoNrf52xMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) :
_sizeData(pixelCount* elementSize + settingsSize),
_pin(pin),
_bus(channel)
{
construct();
}
~NeoNrf52xMethodBase()
@ -261,7 +292,7 @@ public:
bool IsReadyToUpdate() const
{
return (T_BUS::Pwm()->EVENTS_STOPPED);
return (_bus.Pwm()->EVENTS_STOPPED);
}
void Initialize()
@ -306,50 +337,62 @@ public:
private:
const size_t _sizeData; // Size of '_data' buffer below
const uint8_t _pin; // output pin number
const T_BUS _bus; // holds instance for multi channel support
uint8_t* _data; // Holds LED color values
size_t _dmaBufferSize; // total size of _dmaBuffer
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));
// data cleared later in Begin()
_dmaBufferSize = c_dmaBytesPerDataByte * _sizeData + sizeof(nrf_pwm_values_common_t);
_dmaBuffer = static_cast<nrf_pwm_values_common_t*>(malloc(_dmaBufferSize));
}
void dmaInit()
{
// only use channel zero
T_BUS::Pwm()->PSEL.OUT[0] = digitalPinToPinName(_pin);
T_BUS::Pwm()->PSEL.OUT[1] = NC;
T_BUS::Pwm()->PSEL.OUT[2] = NC;
T_BUS::Pwm()->PSEL.OUT[3] = NC;
_bus.Pwm()->PSEL.OUT[0] = digitalPinToPinName(_pin);
_bus.Pwm()->PSEL.OUT[1] = NC;
_bus.Pwm()->PSEL.OUT[2] = NC;
_bus.Pwm()->PSEL.OUT[3] = NC;
T_BUS::Pwm()->ENABLE = 1;
T_BUS::Pwm()->MODE = NRF_PWM_MODE_UP;
T_BUS::Pwm()->PRESCALER = NRF_PWM_CLK_16MHz;
T_BUS::Pwm()->COUNTERTOP = T_SPEED::CountTop;
T_BUS::Pwm()->LOOP = 1; // single fire so events get set
T_BUS::Pwm()->DECODER = NRF_PWM_LOAD_COMMON;
_bus.Pwm()->ENABLE = 1;
_bus.Pwm()->MODE = NRF_PWM_MODE_UP;
_bus.Pwm()->PRESCALER = NRF_PWM_CLK_16MHz;
_bus.Pwm()->COUNTERTOP = T_SPEED::CountTop;
_bus.Pwm()->LOOP = 1; // single fire so events get set
_bus.Pwm()->DECODER = NRF_PWM_LOAD_COMMON;
// sequence zero is the primary data with a BitReset entry on the end for
// the delay repeating
T_BUS::Pwm()->SEQ[0].PTR = reinterpret_cast<uint32_t>(_dmaBuffer);
T_BUS::Pwm()->SEQ[0].CNT = _dmaBufferSize / sizeof(nrf_pwm_values_common_t);
T_BUS::Pwm()->SEQ[0].REFRESH = 0; // ignored
T_BUS::Pwm()->SEQ[0].ENDDELAY = T_SPEED::CountReset; // ignored still?
_bus.Pwm()->SEQ[0].PTR = reinterpret_cast<uint32_t>(_dmaBuffer);
_bus.Pwm()->SEQ[0].CNT = _dmaBufferSize / sizeof(nrf_pwm_values_common_t);
_bus.Pwm()->SEQ[0].REFRESH = 0; // ignored
_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
T_BUS::Pwm()->SEQ[1].PTR = reinterpret_cast<uint32_t>(_dmaBuffer + (T_BUS::Pwm()->SEQ[0].CNT - 1));
T_BUS::Pwm()->SEQ[1].CNT = 1;
T_BUS::Pwm()->SEQ[1].REFRESH = 0; // ignored
T_BUS::Pwm()->SEQ[1].ENDDELAY = 0; // ignored
_bus.Pwm()->SEQ[1].PTR = reinterpret_cast<uint32_t>(_dmaBuffer + (_bus.Pwm()->SEQ[0].CNT - 1));
_bus.Pwm()->SEQ[1].CNT = 1;
_bus.Pwm()->SEQ[1].REFRESH = 0; // ignored
_bus.Pwm()->SEQ[1].ENDDELAY = 0; // ignored
// stop when the loop finishes
T_BUS::Pwm()->SHORTS = PWM_SHORTS_LOOPSDONE_STOP_Msk;
T_BUS::Pwm()->INTEN = 0;
_bus.Pwm()->SHORTS = PWM_SHORTS_LOOPSDONE_STOP_Msk;
_bus.Pwm()->INTEN = 0;
dmaResetEvents();
}
void dmaDeinit()
{
T_BUS::Pwm()->ENABLE = 0;
T_BUS::Pwm()->PSEL.OUT[0] = NC;
_bus.Pwm()->ENABLE = 0;
_bus.Pwm()->PSEL.OUT[0] = NC;
}
void FillBuffer()
@ -379,20 +422,28 @@ private:
void dmaResetEvents()
{
T_BUS::Pwm()->EVENTS_LOOPSDONE = 0;
T_BUS::Pwm()->EVENTS_SEQEND[0] = 0;
T_BUS::Pwm()->EVENTS_SEQEND[1] = 0;
T_BUS::Pwm()->EVENTS_STOPPED = 0;
_bus.Pwm()->EVENTS_LOOPSDONE = 0;
_bus.Pwm()->EVENTS_SEQEND[0] = 0;
_bus.Pwm()->EVENTS_SEQEND[1] = 0;
_bus.Pwm()->EVENTS_STOPPED = 0;
}
void dmaStart()
{
dmaResetEvents();
T_BUS::Pwm()->TASKS_SEQSTART[0] = 1;
_bus.Pwm()->TASKS_SEQSTART[0] = 1;
}
};
// 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<NeoNrf52xPwmSpeedWs2812x, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2812xMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeedSk6812, NeoNrf52xPwm0> NeoNrf52xPwm0Sk6812Method;
@ -428,6 +479,14 @@ typedef NeoNrf52xMethodBase<NeoNrf52xPwmSpeed400Kbps, NeoNrf52xPwm3> NeoNrf52xPw
#endif
// 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<NeoNrf52xPwmInvertedSpeedWs2812x, NeoNrf52xPwm0> NeoNrf52xPwm0Ws2812xInvertedMethod;
typedef NeoNrf52xMethodBase<NeoNrf52xPwmInvertedSpeedSk6812, NeoNrf52xPwm0> NeoNrf52xPwm0Sk6812InvertedMethod;

Some files were not shown because too many files have changed in this diff Show More