Patch 2 (#173)
* 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>
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -10,8 +10,11 @@ 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.
|
||||
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Makuna/NeoPixelBus?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
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.
|
||||
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
@ -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
|
||||
|
@ -536,4 +596,12 @@ NeoTopologyHint_FirstOnPanel LITERAL1
|
|||
NeoTopologyHint_InPanel LITERAL1
|
||||
NeoTopologyHint_LastOnPanel LITERAL1
|
||||
NeoTopologyHint_OutOfBounds LITERAL1
|
||||
PixelIndex_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
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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.
|
|
@ -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)
|
|
@ -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
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// WARNING: This file contains code that is more than likely already
|
||||
// WARNING: This file contains code that is more than likely already
|
||||
// exposed from the Esp32 Arduino API. It will be removed once integration is complete.
|
||||
//
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
|
@ -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;
|
||||
}
|
||||
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)) {
|
||||
|
@ -294,7 +263,7 @@ void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2
|
|||
// (I2S_NUM_MAX == 2)
|
||||
if (bus_num) {
|
||||
periph_module_enable(PERIPH_I2S1_MODULE);
|
||||
} else
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
periph_module_enable(PERIPH_I2S0_MODULE);
|
||||
|
@ -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,12 +332,14 @@ 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);
|
||||
|
||||
// enable intr in cpu //
|
||||
// enable intr in cpu //
|
||||
int i2sIntSource;
|
||||
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
|
@ -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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
xQueueSendFromISR(dev->tx_queue, (void*)&item, &hpTaskAwoken);
|
||||
}
|
||||
|
||||
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
|
|
@ -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);
|
||||
|
|
@ -25,22 +25,17 @@ 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;
|
||||
|
||||
float h = 0.0;
|
||||
float h = 0.0;
|
||||
float v = max;
|
||||
float s = (v == 0.0f) ? 0 : (d / v);
|
||||
|
||||
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
|
@ -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);
|
|
@ -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
|
||||
};
|
|
@ -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;
|
||||
construct(pixelCount, elementSize, settingsSize);
|
||||
}
|
||||
|
||||
_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));
|
||||
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
|
|
@ -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
|
|
@ -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;
|
|
@ -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
|
||||
|
|
@ -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()
|
|
@ -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
|
|
@ -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;
|