Merge remote-tracking branch 'upstream/development' into development

This commit is contained in:
Arik Yavilevich 2020-10-06 18:15:26 +03:00
commit 542f724773
138 changed files with 6610 additions and 2867 deletions

View File

@ -16,8 +16,6 @@ comment: >-
Please, could you be so kind on completing the [issue template](https://github.com/arendst/Tasmota/issues/new/choose) in order to have more information so as to properly help you?
Thank you for taking the time to report, hopefully it can be resolved soon.
[Support Information](https://github.com/arendst/Sonoff-Tasmota/blob/development/SUPPORT.md)
[Wiki](https://tasmota.github.io/docs/) for more information.
@ -25,9 +23,9 @@ comment: >-
[Community](https://groups.google.com/d/forum/sonoffusers) for forum.
[Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md)
[Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md)
[Contributing Guideline and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md)
[Contributing Guideline and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md)
issueConfigs:
# There can be several configs for different kind of issues.

View File

@ -18,6 +18,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-minimal:
runs-on: ubuntu-latest
@ -33,6 +37,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-minimal
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-lite:
runs-on: ubuntu-latest
@ -48,6 +56,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-lite
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-knx:
runs-on: ubuntu-latest
@ -63,7 +75,11 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-knx
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-sensors:
runs-on: ubuntu-latest
steps:
@ -78,7 +94,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-sensors
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-display:
runs-on: ubuntu-latest
@ -94,6 +113,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-display
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-ir:
runs-on: ubuntu-latest
@ -109,6 +132,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-ir
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-zbbridge:
runs-on: ubuntu-latest
@ -124,6 +151,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-zbbridge
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-BG:
runs-on: ubuntu-latest
@ -139,7 +170,11 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-BG
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-BR:
runs-on: ubuntu-latest
steps:
@ -154,6 +189,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-BR
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-CN:
runs-on: ubuntu-latest
@ -169,6 +208,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-CN
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-CZ:
runs-on: ubuntu-latest
@ -184,6 +227,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-CZ
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-DE:
runs-on: ubuntu-latest
@ -199,7 +246,11 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-DE
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-ES:
runs-on: ubuntu-latest
steps:
@ -214,8 +265,11 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-ES
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-FR:
runs-on: ubuntu-latest
steps:
@ -230,6 +284,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-FR
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-GR:
runs-on: ubuntu-latest
@ -245,6 +303,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-GR
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-HE:
runs-on: ubuntu-latest
@ -260,7 +322,11 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-HE
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-HU:
runs-on: ubuntu-latest
steps:
@ -275,6 +341,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-HU
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-IT:
runs-on: ubuntu-latest
@ -290,6 +360,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-IT
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-KO:
runs-on: ubuntu-latest
@ -305,6 +379,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-KO
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-NL:
runs-on: ubuntu-latest
@ -320,7 +398,11 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-NL
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-PL:
runs-on: ubuntu-latest
steps:
@ -335,6 +417,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-PL
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-PT:
runs-on: ubuntu-latest
@ -350,6 +436,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-PT
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-RO:
runs-on: ubuntu-latest
@ -365,6 +455,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-RO
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-RU:
runs-on: ubuntu-latest
@ -380,7 +474,11 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-RU
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-SE:
runs-on: ubuntu-latest
steps:
@ -395,6 +493,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-SE
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-SK:
runs-on: ubuntu-latest
@ -410,6 +512,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-SK
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-TR:
runs-on: ubuntu-latest
@ -425,6 +531,10 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-TR
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-TW:
runs-on: ubuntu-latest
@ -440,7 +550,11 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-TW
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota-UK:
runs-on: ubuntu-latest
steps:
@ -455,3 +569,7 @@ jobs:
platformio update
- name: Run PlatformIO
run: platformio run -e tasmota-UK
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware

View File

@ -19,6 +19,10 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-webcam:
runs-on: ubuntu-latest
@ -35,6 +39,10 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-webcam
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-minimal:
runs-on: ubuntu-latest
@ -51,6 +59,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-minimal
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-lite:
runs-on: ubuntu-latest
steps:
@ -66,6 +79,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-lite
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-knx:
runs-on: ubuntu-latest
steps:
@ -81,6 +99,10 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-knx
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-sensors:
runs-on: ubuntu-latest
@ -97,6 +119,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-sensors
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-display:
runs-on: ubuntu-latest
steps:
@ -112,6 +139,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-display
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-ir:
runs-on: ubuntu-latest
steps:
@ -127,6 +159,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-ir
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-BG:
runs-on: ubuntu-latest
steps:
@ -142,6 +179,10 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-BG
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-BR:
runs-on: ubuntu-latest
@ -158,6 +199,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-BR
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-CN:
runs-on: ubuntu-latest
steps:
@ -173,6 +219,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-CN
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-CZ:
runs-on: ubuntu-latest
steps:
@ -188,6 +239,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-CZ
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-DE:
runs-on: ubuntu-latest
steps:
@ -203,6 +259,10 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-DE
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-ES:
runs-on: ubuntu-latest
@ -219,6 +279,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-ES
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-FR:
runs-on: ubuntu-latest
steps:
@ -234,6 +299,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-FR
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-GR:
runs-on: ubuntu-latest
steps:
@ -249,6 +319,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-GR
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-HE:
runs-on: ubuntu-latest
steps:
@ -264,6 +339,10 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-HE
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-HU:
runs-on: ubuntu-latest
@ -280,6 +359,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-HU
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-IT:
runs-on: ubuntu-latest
steps:
@ -295,6 +379,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-IT
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-KO:
runs-on: ubuntu-latest
steps:
@ -310,6 +399,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-KO
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-NL:
runs-on: ubuntu-latest
steps:
@ -325,6 +419,10 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-NL
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-PL:
runs-on: ubuntu-latest
@ -341,6 +439,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-PL
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-PT:
runs-on: ubuntu-latest
steps:
@ -356,6 +459,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-PT
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-RO:
runs-on: ubuntu-latest
steps:
@ -371,6 +479,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-RO
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-RU:
runs-on: ubuntu-latest
steps:
@ -386,6 +499,10 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-RU
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-SE:
runs-on: ubuntu-latest
@ -402,6 +519,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-SE
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-SK:
runs-on: ubuntu-latest
steps:
@ -417,6 +539,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-SK
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-TR:
runs-on: ubuntu-latest
steps:
@ -432,6 +559,11 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-TR
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-TW:
runs-on: ubuntu-latest
steps:
@ -447,6 +579,10 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-TW
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware
tasmota32-UK:
runs-on: ubuntu-latest
@ -463,3 +599,7 @@ jobs:
- name: Run PlatformIO
run: |
platformio run -e tasmota32-UK
- uses: actions/upload-artifact@v2
with:
name: firmware
path: ./build_output/firmware

4
.gitignore vendored
View File

@ -5,9 +5,7 @@
## Project files ######
.platformio
.pioenvs
.piolibdeps
.pio/libdeps
.pio
.clang_complete
.gcc-flags.json
.cache

View File

@ -61,15 +61,23 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
### Version 9.0.0.1
- Remove auto config update for all Friendlynames and Switchtopic from versions before 8.x
- Remove support for direct upgrade from Tasmota versions before 7.0
- Remove auto config update for all Friendlynames and Switchtopic from Tasmota versions before 8.0
- Change redesigning ESP8266 GPIO internal representation in line with ESP32
- Change new IR Raw compact format (#9444)
- Change MAX31865 driver to support up to 6 thermocouples selected by ``MX31865 CS`` instead of ``SSPI CS`` (#9103)
- Change A4988 optional microstep pin selection
- Change pulsetime to allow use for all relays with 8 interleaved so ``Pulsetime1`` is valid for Relay1, Relay9, Relay17 etc. (#9279)
- Change ``Status`` command output for disabled status types
- Change IRremoteESP8266 library from v2.7.10 to v2.7.11
- Change NeoPixelBus library from v2.5.0.09 to v2.6.0
- Fix template conversion when GPIO17 is 0
- Fix ledlink blink when no network connected regression from 8.3.1.4 (#9292)
- Fix exception 28 due to device group buffer overflow (#9459)
- Fix shutter timing problem due to buffer overflow in calibration matrix (#9458)
- Fix light wakeup exception 0 (divide by zero) when ``WakeupDuration`` is not initialised (#9466)
- Fix ADC initalization sequence (#9473)
- Add optional support for Mitsubishi Electric HVAC by David Gwynne (#9237)
- Add optional support for Orno WE517-Modbus energy meter by Maxime Vincent (#9353)
- Add SDM630 three phase ImportActive Energy display when ``#define SDM630_IMPORT`` is enabled by Janusz Kostorz (#9124)
- Add support for inverted NeoPixelBus data line by enabling ``#define USE_WS2812_INVERTED`` (#8988)

View File

@ -1,275 +0,0 @@
#######################################
# Syntax Coloring Map NeoPixelBus
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
NeoPixelBus KEYWORD1
RgbwColor KEYWORD1
RgbColor KEYWORD1
HslColor KEYWORD1
HsbColor KEYWORD1
HtmlColor KEYWORD1
NeoGrbFeature KEYWORD1
NeoGrbwFeature KEYWORD1
NeoRgbwFeature KEYWORD1
NeoRgbFeature KEYWORD1
NeoBrgFeature KEYWORD1
NeoRbgFeature KEYWORD1
DotStarBgrFeature KEYWORD1
DotStarLbgrFeature KEYWORD1
Neo800KbpsMethod KEYWORD1
Neo400KbpsMethod KEYWORD1
NeoWs2813Method KEYWORD1
NeoWs2812xMethod KEYWORD1
NeoWs2812Method KEYWORD1
NeoSk6812Method KEYWORD1
NeoLc8812Method KEYWORD1
NeoApa106Method KEYWORD1
NeoEsp8266DmaWs2812xMethod KEYWORD1
NeoEsp8266DmaSk6812Method KEYWORD1
NeoEsp8266DmaApa106Method KEYWORD1
NeoEsp8266Dma800KbpsMethod KEYWORD1
NeoEsp8266Dma400KbpsMethod KEYWORD1
NeoEsp8266Uart0Ws2813Method KEYWORD1
NeoEsp8266Uart0Ws2812xMethod KEYWORD1
NeoEsp8266Uart0Ws2812Method KEYWORD1
NeoEsp8266Uart0Sk6812Method KEYWORD1
NeoEsp8266Uart0Lc8812Method KEYWORD1
NeoEsp8266Uart0Apa106Method KEYWORD1
NeoEsp8266Uart0800KbpsMethod KEYWORD1
NeoEsp8266Uart0400KbpsMethod KEYWORD1
NeoEsp8266AsyncUart0Ws2813Method KEYWORD1
NeoEsp8266AsyncUart0Ws2812xMethod KEYWORD1
NeoEsp8266AsyncUart0Ws2812Method KEYWORD1
NeoEsp8266AsyncUart0Sk6812Method KEYWORD1
NeoEsp8266AsyncUart0Lc8812Method KEYWORD1
NeoEsp8266AsyncUart0Apa106Method KEYWORD1
NeoEsp8266AsyncUart0800KbpsMethod KEYWORD1
NeoEsp8266AsyncUart0400KbpsMethod KEYWORD1
NeoEsp8266Uart1Ws2813Method KEYWORD1
NeoEsp8266Uart1Ws2812xMethod KEYWORD1
NeoEsp8266Uart1Ws2812Method KEYWORD1
NeoEsp8266Uart1Sk6812Method KEYWORD1
NeoEsp8266Uart1Lc8812Method KEYWORD1
NeoEsp8266Uart1Apa106Method KEYWORD1
NeoEsp8266Uart1800KbpsMethod KEYWORD1
NeoEsp8266Uart1400KbpsMethod KEYWORD1
NeoEsp8266AsyncUart1Ws2813Method KEYWORD1
NeoEsp8266AsyncUart1Ws2812xMethod KEYWORD1
NeoEsp8266AsyncUart1Ws2812Method KEYWORD1
NeoEsp8266AsyncUart1Sk6812Method KEYWORD1
NeoEsp8266AsyncUart1Lc8812Method KEYWORD1
NeoEsp8266AsyncUart1Apa106Method KEYWORD1
NeoEsp8266AsyncUart1800KbpsMethod KEYWORD1
NeoEsp8266AsyncUart1400KbpsMethod KEYWORD1
NeoEsp8266BitBangWs2813Method KEYWORD1
NeoEsp8266BitBangWs2812xMethod KEYWORD1
NeoEsp8266BitBangWs2812Method KEYWORD1
NeoEsp8266BitBangSk6812Method KEYWORD1
NeoEsp8266BitBangLc8812Method KEYWORD1
NeoEsp8266BitBangApa106Method KEYWORD1
NeoEsp8266BitBang800KbpsMethod KEYWORD1
NeoEsp8266BitBang400KbpsMethod KEYWORD1
NeoEsp32Rmt0Ws2812xMethod KEYWORD1
NeoEsp32Rmt0Sk6812Method KEYWORD1
NeoEsp32Rmt0Apa106Method KEYWORD1
NeoEsp32Rmt0800KbpsMethod KEYWORD1
NeoEsp32Rmt0400KbpsMethod KEYWORD1
NeoEsp32Rmt1Ws2812xMethod KEYWORD1
NeoEsp32Rmt1Sk6812Method KEYWORD1
NeoEsp32Rmt1Apa106Method KEYWORD1
NeoEsp32Rmt1800KbpsMethod KEYWORD1
NeoEsp32Rmt1400KbpsMethod KEYWORD1
NeoEsp32Rmt2Ws2812xMethod KEYWORD1
NeoEsp32Rmt2Sk6812Method KEYWORD1
NeoEsp32Rmt2Apa106Method KEYWORD1
NeoEsp32Rmt2800KbpsMethod KEYWORD1
NeoEsp32Rmt2400KbpsMethod KEYWORD1
NeoEsp32Rmt3Ws2812xMethod KEYWORD1
NeoEsp32Rmt3Sk6812Method KEYWORD1
NeoEsp32Rmt3Apa106Method KEYWORD1
NeoEsp32Rmt3800KbpsMethod KEYWORD1
NeoEsp32Rmt3400KbpsMethod KEYWORD1
NeoEsp32Rmt4Ws2812xMethod KEYWORD1
NeoEsp32Rmt4Sk6812Method KEYWORD1
NeoEsp32Rmt4Apa106Method KEYWORD1
NeoEsp32Rmt4800KbpsMethod KEYWORD1
NeoEsp32Rmt4400KbpsMethod KEYWORD1
NeoEsp32Rmt5Ws2812xMethod KEYWORD1
NeoEsp32Rmt5Sk6812Method KEYWORD1
NeoEsp32Rmt5Apa106Method KEYWORD1
NeoEsp32Rmt5800KbpsMethod KEYWORD1
NeoEsp32Rmt5400KbpsMethod KEYWORD1
NeoEsp32Rmt6Ws2812xMethod KEYWORD1
NeoEsp32Rmt6Sk6812Method KEYWORD1
NeoEsp32Rmt6Apa106Method KEYWORD1
NeoEsp32Rmt6800KbpsMethod KEYWORD1
NeoEsp32Rmt6400KbpsMethod KEYWORD1
NeoEsp32Rmt7Ws2812xMethod KEYWORD1
NeoEsp32Rmt7Sk6812Method KEYWORD1
NeoEsp32Rmt7Apa106Method KEYWORD1
NeoEsp32Rmt7800KbpsMethod KEYWORD1
NeoEsp32Rmt7400KbpsMethod KEYWORD1
NeoEsp32BitBangWs2813Method KEYWORD1
NeoEsp32BitBangWs2812xMethod KEYWORD1
NeoEsp32BitBangWs2812Method KEYWORD1
NeoEsp32BitBangSk6812Method KEYWORD1
NeoEsp32BitBangLc8812Method KEYWORD1
NeoEsp32BitBangApa106Method KEYWORD1
NeoEsp32BitBang800KbpsMethod KEYWORD1
NeoEsp32BitBang400KbpsMethod KEYWORD1
DotStarMethod KEYWORD1
DotStarSpiMethod KEYWORD1
NeoPixelAnimator KEYWORD1
AnimUpdateCallback KEYWORD1
AnimationParam KEYWORD1
NeoEase KEYWORD1
AnimEaseFunction KEYWORD1
RowMajorLayout KEYWORD1
RowMajor90Layout KEYWORD1
RowMajor180Layout KEYWORD1
RowMajor270Layout KEYWORD1
RowMajorAlternatingLayout KEYWORD1
RowMajorAlternating90Layout KEYWORD1
RowMajorAlternating180Layout KEYWORD1
RowMajorAlternating270Layout KEYWORD1
ColumnMajorLayout KEYWORD1
ColumnMajor90Layout KEYWORD1
ColumnMajor180Layout KEYWORD1
ColumnMajor270Layout KEYWORD1
ColumnMajorAlternatingLayout KEYWORD1
ColumnMajorAlternating90Layout KEYWORD1
ColumnMajorAlternating180Layout KEYWORD1
ColumnMajorAlternating270Layout KEYWORD1
NeoTopology KEYWORD1
NeoRingTopology KEYWORD1
NeoTiles KEYWORD1
NeoMosaic KEYWORD1
NeoGammaEquationMethod KEYWORD1
NeoGammaTableMethod KEYWORD1
NeoGamma KEYWORD1
NeoHueBlendShortestDistance KEYWORD1
NeoHueBlendLongestDistance KEYWORD1
NeoHueBlendClockwiseDirection KEYWORD1
NeoHueBlendCounterClockwiseDirection KEYWORD1
NeoBufferContext KEYWORD1
LayoutMapCallback KEYWORD1
NeoBufferMethod KEYWORD1
NeoBufferProgmemMethod KEYWORD1
NeoBuffer KEYWORD1
NeoVerticalSpriteSheet KEYWORD1
NeoBitmapFile KEYWORD1
HtmlShortColorNames KEYWORD1
HtmlColorNames KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
Begin KEYWORD2
Show KEYWORD2
CanShow KEYWORD2
ClearTo KEYWORD2
RotateLeft KEYWORD2
ShiftLeft KEYWORD2
RotateRight KEYWORD2
ShiftRight KEYWORD2
IsDirty KEYWORD2
Dirty KEYWORD2
ResetDirty KEYWORD2
Pixels KEYWORD2
PixelsSize KEYWORD2
PixelCount KEYWORD2
SetPixelColor KEYWORD2
GetPixelColor KEYWORD2
SwapPixelColor KEYWORD2
CalculateBrightness KEYWORD2
Darken KEYWORD2
Lighten KEYWORD2
LinearBlend KEYWORD2
BilinearBlend KEYWORD2
IsAnimating KEYWORD2
NextAvailableAnimation KEYWORD2
StartAnimation KEYWORD2
StopAnimation KEYWORD2
RestartAnimation KEYWORD2
IsAnimationActive KEYWORD2
AnimationDuration KEYWORD2
ChangeAnimationDuration KEYWORD2
UpdateAnimations KEYWORD2
IsPaused KEYWORD2
Pause KEYWORD2
Resume KEYWORD2
getTimeScale KEYWORD2
setTimeScale KEYWORD2
QuadraticIn KEYWORD2
QuadraticOut KEYWORD2
QuadraticInOut KEYWORD2
QuadraticCenter KEYWORD2
CubicIn KEYWORD2
CubicOut KEYWORD2
CubicInOut KEYWORD2
CubicCenter KEYWORD2
QuarticIn KEYWORD2
QuarticOut KEYWORD2
QuarticInOut KEYWORD2
QuarticCenter KEYWORD2
QuinticIn KEYWORD2
QuinticOut KEYWORD2
QuinticInOut KEYWORD2
QuinticCenter KEYWORD2
SinusoidalIn KEYWORD2
SinusoidalOut KEYWORD2
SinusoidalInOut KEYWORD2
SinusoidalCenter KEYWORD2
ExponentialIn KEYWORD2
ExponentialOut KEYWORD2
ExponentialInOut KEYWORD2
ExponentialCenter KEYWORD2
CircularIn KEYWORD2
CircularOut KEYWORD2
CircularInOut KEYWORD2
CircularCenter KEYWORD2
Gamma KEYWORD2
Map KEYWORD2
MapProbe KEYWORD2
getWidth KEYWORD2
getHeight KEYWORD2
RingPixelShift KEYWORD2
RingPixelRotate KEYWORD2
getCountOfRings KEYWORD2
getPixelCountAtRing KEYWORD2
getPixelCount KEYWORD2
TopologyHint KEYWORD2
Correct KEYWORD2
SpriteWidth KEYWORD2
SpriteHeight KEYWORD2
SpriteCount KEYWORD2
Blt KEYWORD2
Width KEYWORD2
Height KEYWORD2
Parse KEYWORD2
ToString KEYWORD2
ToNumericalString KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
NEO_MILLISECONDS LITERAL1
NEO_CENTISECONDS LITERAL1
NEO_DECISECONDS LITERAL1
NEO_SECONDS LITERAL1
NEO_DECASECONDS LITERAL1
AnimationState_Started LITERAL1
AnimationState_Progress LITERAL1
AnimationState_Completed LITERAL1
NeoTopologyHint_FirstOnPanel LITERAL1
NeoTopologyHint_InPanel LITERAL1
NeoTopologyHint_LastOnPanel LITERAL1
NeoTopologyHint_OutOfBounds LITERAL1
PixelIndex_OutOfBounds LITERAL1

View File

@ -1,14 +0,0 @@
{
"name": "NeoPixelBus",
"keywords": "NeoPixel, WS2811, WS2812, WS2813, SK6812, DotStar, APA102, RGB, RGBW",
"description": "A library that makes controlling NeoPixels (WS2811, WS2812, WS2813 & SK6812) and DotStars (APA102) easy. Supports most Arduino platforms. Support for RGBW pixels. Includes seperate RgbColor, RgbwColor, HslColor, and HsbColor objects. Includes an animator class that helps create asyncronous animations. For Esp8266 it has three methods of sending NeoPixel data, DMA, UART, and Bit Bang. For Esp32 it has two base methods of sending NeoPixel data, i2s and RMT. For all platforms, there are two methods of sending DotStar data, hardware SPI and software SPI.",
"homepage": "https://github.com/Makuna/NeoPixelBus/wiki",
"repository": {
"type": "git",
"url": "https://github.com/Makuna/NeoPixelBus"
},
"version": "2.5.0",
"frameworks": "arduino",
"platforms": "*"
}

View File

@ -1,9 +0,0 @@
name=NeoPixelBus by Makuna
version=2.5.0
author=Michael C. Miller (makuna@live.com)
maintainer=Michael C. Miller (makuna@live.com)
sentence=A library that makes controlling NeoPixels (WS2811, WS2812, WS2813 & SK6812) and DotStars (APA102) easy.
paragraph=Supports most Arduino platforms, including Esp8266 and Esp32. Support for RGBW pixels. Includes seperate RgbColor, RgbwColor, HslColor, and HsbColor objects. Includes an animator class that helps create asyncronous animations. Supports Matrix layout of pixels. Includes Gamma corretion object. For Esp8266 it has three methods of sending NeoPixel data, DMA, UART, and Bit Bang. For Esp32 it has two base methods of sending NeoPixel data, i2s and RMT. For all platforms, there are two methods of sending DotStar data, hardware SPI and software SPI.
category=Display
url=https://github.com/Makuna/NeoPixelBus/wiki
architectures=*

View File

@ -1,133 +0,0 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for DotStars using SPI hardware (APA102).
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
#include <SPI.h>
class DotStarSpiMethod
{
public:
DotStarSpiMethod(uint16_t pixelCount, size_t elementSize) :
_sizeData(pixelCount * elementSize),
_sizeSendBuffer(calcBufferSize(pixelCount * elementSize))
{
_sendBuffer = (uint8_t*)malloc(_sizeSendBuffer);
memset(_sendBuffer, 0, _sizeSendBuffer);
setEndFrameBytes();
}
~DotStarSpiMethod()
{
SPI.end();
free(_sendBuffer);
}
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)
{
SPI.begin(sck, miso, mosi, ss);
}
#endif
void Initialize()
{
SPI.begin();
}
void Update(bool)
{
SPI.beginTransaction(SPISettings(20000000L, MSBFIRST, SPI_MODE0));
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
// ESPs have a method to write without inplace overwriting the send buffer
// since we don't care what gets received, use it for performance
SPI.writeBytes(_sendBuffer, _sizeSendBuffer);
#else
// default ARDUINO transfer inplace overwrites the send buffer
// which is bad, so we have to send one byte at a time
uint8_t* out = _sendBuffer;
uint8_t* end = out + _sizeSendBuffer;
while (out < end)
{
SPI.transfer(*out++);
}
#endif
SPI.endTransaction();
}
uint8_t* getPixels() const
{
return _sendBuffer + _countStartFrame;
};
size_t getPixelsSize() const
{
return _sizeData;
};
private:
const size_t _countStartFrame = 4;
const size_t _sizeData; // size of actuall pixel data within _sendBuffer
const size_t _sizeSendBuffer; // Size of '_sendBuffer' buffer below
uint8_t* _sendBuffer; // Holds SPI send Buffer, including LED color values
size_t calcBufferSize(size_t sizePixels) const
{
const size_t countEndFrameBytes = calcEndFrameSize(sizePixels);
// start frame + data + end frame
const size_t bufferSize = _countStartFrame + sizePixels + countEndFrameBytes;
return bufferSize;
}
size_t calcEndFrameSize(size_t sizePixels) const
{
// end frame
// one bit for every two pixels with no less than 1 byte
return ((sizePixels / 4) + 15) / 16;
}
void setEndFrameBytes()
{
uint8_t* pEndFrame = _sendBuffer + _countStartFrame + _sizeData;
uint8_t* pEndFrameStop = pEndFrame + calcEndFrameSize(_sizeData);
while (pEndFrame != pEndFrameStop)
{
*pEndFrame++ = 0xff;
}
}
};

View File

@ -1,217 +0,0 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp32.
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
#ifdef ARDUINO_ARCH_ESP32
extern "C"
{
#include <Arduino.h>
#include "Esp32_i2s.h"
}
const uint16_t c_dmaBytesPerPixelBytes = 4;
class NeoEsp32I2sSpeedWs2812x
{
public:
const static uint32_t I2sSampleRate = 100000;
const static uint16_t ByteSendTimeUs = 10;
const static uint16_t ResetTimeUs = 300;
};
class NeoEsp32I2sSpeedSk6812
{
public:
const static uint32_t I2sSampleRate = 100000;
const static uint16_t ByteSendTimeUs = 10;
const static uint16_t ResetTimeUs = 80;
};
class NeoEsp32I2sSpeed800Kbps
{
public:
const static uint32_t I2sSampleRate = 100000;
const static uint16_t ByteSendTimeUs = 10;
const static uint16_t ResetTimeUs = 50;
};
class NeoEsp32I2sSpeed400Kbps
{
public:
const static uint32_t I2sSampleRate = 50000;
const static uint16_t ByteSendTimeUs = 20;
const static uint16_t ResetTimeUs = 50;
};
class NeoEsp32I2sSpeedApa106
{
public:
const static uint32_t I2sSampleRate = 76000;
const static uint16_t ByteSendTimeUs = 14;
const static uint16_t ResetTimeUs = 50;
};
class NeoEsp32I2sBusZero
{
public:
const static uint8_t I2sBusNumber = 0;
};
class NeoEsp32I2sBusOne
{
public:
const static uint8_t I2sBusNumber = 1;
};
template<typename T_SPEED, typename T_BUS> class NeoEsp32I2sMethodBase
{
public:
NeoEsp32I2sMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) :
_pin(pin)
{
uint16_t dmaPixelSize = c_dmaBytesPerPixelBytes * elementSize;
uint16_t resetSize = c_dmaBytesPerPixelBytes * T_SPEED::ResetTimeUs / T_SPEED::ByteSendTimeUs;
_pixelsSize = pixelCount * elementSize;
_i2sBufferSize = pixelCount * dmaPixelSize + resetSize;
// must have a 4 byte aligned buffer for i2s
uint32_t alignment = _i2sBufferSize % 4;
if (alignment)
{
_i2sBufferSize += 4 - alignment;
}
_pixels = static_cast<uint8_t*>(malloc(_pixelsSize));
memset(_pixels, 0x00, _pixelsSize);
_i2sBuffer = static_cast<uint8_t*>(malloc(_i2sBufferSize));
memset(_i2sBuffer, 0x00, _i2sBufferSize);
}
~NeoEsp32I2sMethodBase()
{
while (!IsReadyToUpdate())
{
yield();
}
pinMode(_pin, INPUT);
free(_pixels);
free(_i2sBuffer);
}
bool IsReadyToUpdate() const
{
return (i2sWriteDone(T_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, -1, -1, -1);
}
void Update(bool)
{
// wait for not actively sending data
while (!IsReadyToUpdate())
{
yield();
}
FillBuffers();
i2sWrite(T_BUS::I2sBusNumber, _i2sBuffer, _i2sBufferSize, false, false);
}
uint8_t* getPixels() const
{
return _pixels;
};
size_t getPixelsSize() const
{
return _pixelsSize;
}
private:
const uint8_t _pin; // output pin number
size_t _pixelsSize; // Size of '_pixels' buffer
uint8_t* _pixels; // Holds LED color values
uint32_t _i2sBufferSize; // total size of _i2sBuffer
uint8_t* _i2sBuffer; // holds the DMA buffer that is referenced by _i2sBufDesc
void FillBuffers()
{
const uint16_t bitpatterns[16] =
{
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
uint16_t* pDma = reinterpret_cast<uint16_t*>(_i2sBuffer);
uint8_t* pPixelsEnd = _pixels + _pixelsSize;
for (uint8_t* pPixel = _pixels; pPixel < pPixelsEnd; pPixel++)
{
*(pDma++) = bitpatterns[((*pPixel) & 0x0f)];
*(pDma++) = bitpatterns[((*pPixel) >> 4) & 0x0f];
}
}
};
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusZero> NeoEsp32I2s0Ws2812xMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusZero> NeoEsp32I2s0Sk6812Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusZero> NeoEsp32I2s0800KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusZero> NeoEsp32I2s0400KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusZero> NeoEsp32I2s0Apa106Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusOne> NeoEsp32I2s1Ws2812xMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusOne> NeoEsp32I2s1Sk6812Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusOne> NeoEsp32I2s1800KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusOne> NeoEsp32I2s1400KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusOne> NeoEsp32I2s1Apa106Method;
// I2s Bus 1 method is the default method for Esp32
typedef NeoEsp32I2s1Ws2812xMethod NeoWs2813Method;
typedef NeoEsp32I2s1Ws2812xMethod NeoWs2812xMethod;
typedef NeoEsp32I2s1800KbpsMethod NeoWs2812Method;
typedef NeoEsp32I2s1Sk6812Method NeoSk6812Method;
typedef NeoEsp32I2s1Sk6812Method NeoLc8812Method;
typedef NeoEsp32I2s1Apa106Method NeoApa106Method;
typedef NeoEsp32I2s1Ws2812xMethod Neo800KbpsMethod;
typedef NeoEsp32I2s1400KbpsMethod Neo400KbpsMethod;
#endif

View File

@ -1,369 +0,0 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp32.
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
#ifdef ARDUINO_ARCH_ESP32
/* General Reference documentation for the APIs used in this implementation
LOW LEVEL: (what is actually used)
DOCS: https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html
EXAMPLE: https://github.com/espressif/esp-idf/blob/826ff7186ae07dc81e960a8ea09ebfc5304bfb3b/examples/peripherals/rmt_tx/main/rmt_tx_main.c
HIGHER LEVEL:
NO TRANSLATE SUPPORT so this was not used
NOTE: https://github.com/espressif/arduino-esp32/commit/50d142950d229b8fabca9b749dc4a5f2533bc426
Esp32-hal-rmt.h
Esp32-hal-rmt.c
*/
extern "C"
{
#include <Arduino.h>
#include <driver/rmt.h>
}
class NeoEsp32RmtSpeedBase
{
public:
// ClkDiv of 2 provides for good resolution and plenty of reset resolution; but
// a ClkDiv of 1 will provide enough space for the longest reset and does show
// little better pulse accuracy
const static uint8_t RmtClockDivider = 2;
inline constexpr static uint32_t FromNs(uint32_t ns)
{
return ns / NsPerRmtTick;
}
// this is used rather than the rmt_item32_t as you can't correctly initialize
// it as a static constexpr within the template
inline constexpr static uint32_t Item32Val(uint16_t nsHigh, uint16_t nsLow)
{
return (FromNs(nsLow) << 16) | (1 << 15) | (FromNs(nsHigh));
}
public:
const static uint32_t RmtCpu = 80000000L; // 80 mhz RMT clock
const static uint32_t NsPerSecond = 1000000000L;
const static uint32_t RmtTicksPerSecond = (RmtCpu / RmtClockDivider);
const static uint32_t NsPerRmtTick = (NsPerSecond / RmtTicksPerSecond); // about 25
};
class NeoEsp32RmtSpeedWs2812x : public NeoEsp32RmtSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(400, 850);
const static uint32_t RmtBit1 = Item32Val(800, 450);
const static uint16_t RmtDurationReset = FromNs(300000); // 300us
};
class NeoEsp32RmtSpeedSk6812 : public NeoEsp32RmtSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(400, 850);
const static uint32_t RmtBit1 = Item32Val(800, 450);
const static uint16_t RmtDurationReset = FromNs(80000); // 80us
};
class NeoEsp32RmtSpeed800Kbps : public NeoEsp32RmtSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(400, 850);
const static uint32_t RmtBit1 = Item32Val(800, 450);
const static uint16_t RmtDurationReset = FromNs(50000); // 50us
};
class NeoEsp32RmtSpeed400Kbps : public NeoEsp32RmtSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(800, 1700);
const static uint32_t RmtBit1 = Item32Val(1600, 900);
const static uint16_t RmtDurationReset = FromNs(50000); // 50us
};
class NeoEsp32RmtSpeedApa106 : public NeoEsp32RmtSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(400, 1250);
const static uint32_t RmtBit1 = Item32Val(1250, 400);
const static uint16_t RmtDurationReset = FromNs(50000); // 50us
};
class NeoEsp32RmtChannel0
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_0;
};
class NeoEsp32RmtChannel1
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_1;
};
class NeoEsp32RmtChannel2
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_2;
};
class NeoEsp32RmtChannel3
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_3;
};
class NeoEsp32RmtChannel4
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_4;
};
class NeoEsp32RmtChannel5
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_5;
};
class NeoEsp32RmtChannel6
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_6;
};
class NeoEsp32RmtChannel7
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_7;
};
template<typename T_SPEED, typename T_CHANNEL> class NeoEsp32RmtMethodBase
{
public:
NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) :
_pin(pin)
{
_pixelsSize = pixelCount * elementSize;
_pixelsEditing = static_cast<uint8_t*>(malloc(_pixelsSize));
memset(_pixelsEditing, 0x00, _pixelsSize);
_pixelsSending = static_cast<uint8_t*>(malloc(_pixelsSize));
// no need to initialize it, it gets overwritten on every send
}
~NeoEsp32RmtMethodBase()
{
// wait until the last send finishes before destructing everything
// arbitrary time out of 10 seconds
rmt_wait_tx_done(T_CHANNEL::RmtChannelNumber, 10000 / portTICK_PERIOD_MS);
rmt_driver_uninstall(T_CHANNEL::RmtChannelNumber);
free(_pixelsEditing);
free(_pixelsSending);
}
bool IsReadyToUpdate() const
{
return (ESP_OK == rmt_wait_tx_done(T_CHANNEL::RmtChannelNumber, 0));
}
void Initialize()
{
rmt_config_t config;
config.rmt_mode = RMT_MODE_TX;
config.channel = T_CHANNEL::RmtChannelNumber;
config.gpio_num = static_cast<gpio_num_t>(_pin);
config.mem_block_num = 1;
config.tx_config.loop_en = false;
config.tx_config.idle_output_en = true;
config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
config.tx_config.carrier_en = false;
config.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
config.clk_div = T_SPEED::RmtClockDivider;
rmt_config(&config);
rmt_driver_install(T_CHANNEL::RmtChannelNumber, 0, 0);
rmt_translator_init(T_CHANNEL::RmtChannelNumber, _translate);
}
void Update(bool maintainBufferConsistency)
{
// 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 == rmt_wait_tx_done(T_CHANNEL::RmtChannelNumber, 10000 / portTICK_PERIOD_MS))
{
// now start the RMT transmit with the editing buffer before we swap
rmt_write_sample(T_CHANNEL::RmtChannelNumber, _pixelsEditing, _pixelsSize, false);
if (maintainBufferConsistency)
{
// copy editing to sending,
// this maintains the contract that "colors present before will
// be the same after", otherwise GetPixelColor will be inconsistent
memcpy(_pixelsSending, _pixelsEditing, _pixelsSize);
}
// swap so the user can modify without affecting the async operation
std::swap(_pixelsSending, _pixelsEditing);
}
}
uint8_t* getPixels() const
{
return _pixelsEditing;
};
size_t getPixelsSize() const
{
return _pixelsSize;
}
private:
const uint8_t _pin; // output pin number
size_t _pixelsSize; // Size of '_pixels' buffer
uint8_t* _pixelsEditing; // Holds LED color values exposed for get and set
uint8_t* _pixelsSending; // Holds LED color values used to async send using RMT
// stranslate NeoPixelBuffer into RMT buffer
// this is done on the fly so we don't require a send buffer in raw RMT format
// which would be 32x larger than the primary buffer
static void IRAM_ATTR _translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
if (src == NULL || dest == NULL)
{
*translated_size = 0;
*item_num = 0;
return;
}
size_t size = 0;
size_t num = 0;
const uint8_t* psrc = static_cast<const uint8_t*>(src);
rmt_item32_t* pdest = dest;
for (;;)
{
uint8_t data = *psrc;
for (uint8_t bit = 0; bit < 8; bit++)
{
pdest->val = (data & 0x80) ? T_SPEED::RmtBit1 : T_SPEED::RmtBit0;
pdest++;
data <<= 1;
}
num += 8;
size++;
// if this is the last byte we need to adjust the length of the last pulse
if (size >= src_size)
{
// extend the last bits LOW value to include the full reset signal length
pdest--;
pdest->duration1 = T_SPEED::RmtDurationReset;
// and stop updating data to send
break;
}
if (num >= wanted_num)
{
// stop updating data to send
break;
}
psrc++;
}
*translated_size = size;
*item_num = num;
}
};
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel0> NeoEsp32Rmt0Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel0> NeoEsp32Rmt0800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel0> NeoEsp32Rmt0400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel1> NeoEsp32Rmt1Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel1> NeoEsp32Rmt1Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel1> NeoEsp32Rmt1Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel1> NeoEsp32Rmt1800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel1> NeoEsp32Rmt1400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel2> NeoEsp32Rmt2Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel2> NeoEsp32Rmt2Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel2> NeoEsp32Rmt2Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel2> NeoEsp32Rmt2800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel2> NeoEsp32Rmt2400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel3> NeoEsp32Rmt3Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel3> NeoEsp32Rmt3Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel3> NeoEsp32Rmt3Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel3> NeoEsp32Rmt3800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel3> NeoEsp32Rmt3400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel4> NeoEsp32Rmt4Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel4> NeoEsp32Rmt4Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel4> NeoEsp32Rmt4Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel4> NeoEsp32Rmt4800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel4> NeoEsp32Rmt4400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel5> NeoEsp32Rmt5Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel5> NeoEsp32Rmt5Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel5> NeoEsp32Rmt5Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel5> NeoEsp32Rmt5800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel5> NeoEsp32Rmt5400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel6> NeoEsp32Rmt6Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel6> NeoEsp32Rmt6Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel6> NeoEsp32Rmt6Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel6> NeoEsp32Rmt6800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel6> NeoEsp32Rmt6400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel7> NeoEsp32Rmt7Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel7> NeoEsp32Rmt7Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel7> NeoEsp32Rmt7Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7400KbpsMethod;
// RMT is NOT the default method for Esp32,
// you are required to use a specific channel listed above
#endif

View File

@ -1,434 +0,0 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp8266 UART hardware
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
#ifdef ARDUINO_ARCH_ESP8266
#include <Arduino.h>
// this template method class is used to track the data being sent on the uart
// when using the default serial ISR installed by the core
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
//
class NeoEsp8266UartContext
{
public:
// Gets the number of bytes waiting in the TX FIFO
static inline uint8_t ICACHE_RAM_ATTR GetTxFifoLength(uint8_t uartNum)
{
return (USS(uartNum) >> USTXC) & 0xff;
}
// Append a byte to the TX FIFO
static inline void ICACHE_RAM_ATTR Enqueue(uint8_t uartNum, uint8_t value)
{
USF(uartNum) = value;
}
static const volatile uint8_t* ICACHE_RAM_ATTR FillUartFifo(uint8_t uartNum,
const volatile uint8_t* pixels,
const volatile uint8_t* end);
};
// this template method class is used to track the data being sent on the uart
// when using our own UART ISR
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
//
class NeoEsp8266UartInterruptContext : NeoEsp8266UartContext
{
public:
NeoEsp8266UartInterruptContext() :
_asyncBuff(nullptr),
_asyncBuffEnd(nullptr)
{
}
bool IsSending()
{
return (_asyncBuff != _asyncBuffEnd);
}
void StartSending(uint8_t uartNum, uint8_t* start, uint8_t* end);
void Attach(uint8_t uartNum);
void Detach(uint8_t uartNum);
private:
volatile const uint8_t* _asyncBuff;
volatile const uint8_t* _asyncBuffEnd;
volatile static NeoEsp8266UartInterruptContext* s_uartInteruptContext[2];
static void ICACHE_RAM_ATTR Isr(void* param);
};
// this template feature class is used a base for all others and contains
// common methods
//
class UartFeatureBase
{
protected:
static void ConfigUart(uint8_t uartNum)
{
// clear all invert bits
USC0(uartNum) &= ~((1 << UCDTRI) | (1 << UCRTSI) | (1 << UCTXI) | (1 << UCDSRI) | (1 << UCCTSI) | (1 << UCRXI));
// Invert the TX voltage associated with logic level so:
// - A logic level 0 will generate a Vcc signal
// - A logic level 1 will generate a Gnd signal
USC0(uartNum) |= (1 << UCTXI);
}
};
// this template feature class is used to define the specifics for uart0
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
//
class UartFeature0 : UartFeatureBase
{
public:
static const uint32_t Index = 0;
static void Init(uint32_t baud)
{
// Configure the serial line with 1 start bit (0), 6 data bits and 1 stop bit (1)
Serial.begin(baud, SERIAL_6N1, SERIAL_TX_ONLY);
ConfigUart(Index);
}
};
// this template feature class is used to define the specifics for uart1
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
//
class UartFeature1 : UartFeatureBase
{
public:
static const uint32_t Index = 1;
static void Init(uint32_t baud)
{
// Configure the serial line with 1 start bit (0), 6 data bits and 1 stop bit (1)
Serial1.begin(baud, SERIAL_6N1, SERIAL_TX_ONLY);
ConfigUart(Index);
}
};
// this template method class is used a base for all others and contains
// common properties and methods
//
// used by NeoEsp8266Uart and NeoEsp8266AsyncUart
//
class NeoEsp8266UartBase
{
protected:
size_t _sizePixels; // Size of '_pixels' buffer below
uint8_t* _pixels; // Holds LED color values
uint32_t _startTime; // Microsecond count when last update started
NeoEsp8266UartBase(uint16_t pixelCount, size_t elementSize)
{
_sizePixels = pixelCount * elementSize;
_pixels = (uint8_t*)malloc(_sizePixels);
memset(_pixels, 0x00, _sizePixels);
}
~NeoEsp8266UartBase()
{
free(_pixels);
}
};
// this template method class is used to glue uart feature and context for
// synchronous uart method
//
// used by NeoEsp8266UartMethodBase
//
template<typename T_UARTFEATURE, typename T_UARTCONTEXT> class NeoEsp8266Uart : public NeoEsp8266UartBase
{
protected:
NeoEsp8266Uart(uint16_t pixelCount, size_t elementSize) :
NeoEsp8266UartBase(pixelCount, elementSize)
{
}
~NeoEsp8266Uart()
{
// Wait until the TX fifo is empty. This way we avoid broken frames
// when destroying & creating a NeoPixelBus to change its length.
while (T_UARTCONTEXT::GetTxFifoLength(T_UARTFEATURE::Index) > 0)
{
yield();
}
}
void InitializeUart(uint32_t uartBaud)
{
T_UARTFEATURE::Init(uartBaud);
}
void UpdateUart(bool)
{
// Since the UART can finish sending queued bytes in the FIFO in
// the background, instead of waiting for the FIFO to flush
// we annotate the start time of the frame so we can calculate
// when it will finish.
_startTime = micros();
// Then keep filling the FIFO until done
const uint8_t* ptr = _pixels;
const uint8_t* end = ptr + _sizePixels;
while (ptr != end)
{
ptr = const_cast<uint8_t*>(T_UARTCONTEXT::FillUartFifo(T_UARTFEATURE::Index, ptr, end));
}
}
};
// this template method class is used to glue uart feature and context for
// asynchronously uart method
//
// This UART controller uses two buffers that are swapped in every call to
// NeoPixelBus.Show(). One buffer contains the data that is being sent
// asynchronosly and another buffer contains the data that will be send
// in the next call to NeoPixelBus.Show().
//
// Therefore, the result of NeoPixelBus.Pixels() is invalidated after
// every call to NeoPixelBus.Show() and must not be cached.
//
// used by NeoEsp8266UartMethodBase
//
template<typename T_UARTFEATURE, typename T_UARTCONTEXT> class NeoEsp8266AsyncUart : public NeoEsp8266UartBase
{
protected:
NeoEsp8266AsyncUart(uint16_t pixelCount, size_t elementSize) :
NeoEsp8266UartBase(pixelCount, elementSize)
{
_pixelsSending = (uint8_t*)malloc(_sizePixels);
}
~NeoEsp8266AsyncUart()
{
// Remember: the UART interrupt can be sending data from _pixelsSending in the background
while (_context.IsSending())
{
yield();
}
// detach context, which will disable intr, may disable ISR
_context.Detach(T_UARTFEATURE::Index);
free(_pixelsSending);
}
void ICACHE_RAM_ATTR InitializeUart(uint32_t uartBaud)
{
T_UARTFEATURE::Init(uartBaud);
// attach the context, which will enable the ISR
_context.Attach(T_UARTFEATURE::Index);
}
void UpdateUart(bool maintainBufferConsistency)
{
// Instruct ESP8266 hardware uart to send the pixels asynchronously
_context.StartSending(T_UARTFEATURE::Index,
_pixels,
_pixels + _sizePixels);
// Annotate when we started to send bytes, so we can calculate when we are ready to send again
_startTime = micros();
if (maintainBufferConsistency)
{
// copy editing to sending,
// this maintains the contract that "colors present before will
// be the same after", otherwise GetPixelColor will be inconsistent
memcpy(_pixelsSending, _pixels, _sizePixels);
}
// swap so the user can modify without affecting the async operation
// std::swap(_pixelsSending, _pixels);
uint8_t *temp = _pixelsSending;
_pixelsSending = _pixels;
_pixels = temp;
}
private:
T_UARTCONTEXT _context;
uint8_t* _pixelsSending; // Holds a copy of LED color values taken when UpdateUart began
};
class NeoEsp8266UartSpeed800KbpsBase
{
public:
static const uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed
static const uint32_t UartBaud = 3200000; // 800mhz, 4 serial bytes per NeoByte
};
// NeoEsp8266UartSpeedWs2813 contains the timing constants used to get NeoPixelBus running with the Ws2813
class NeoEsp8266UartSpeedWs2812x : public NeoEsp8266UartSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 300; // us between data send bursts to reset for next update
};
class NeoEsp8266UartSpeedSk6812 : public NeoEsp8266UartSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 80; // us between data send bursts to reset for next update
};
// NeoEsp8266UartSpeed800Kbps contains the timing constant used to get NeoPixelBus running at 800Khz
class NeoEsp8266UartSpeed800Kbps : public NeoEsp8266UartSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update
};
// NeoEsp8266UartSpeed400Kbps contains the timing constant used to get NeoPixelBus running at 400Khz
class NeoEsp8266UartSpeed400Kbps
{
public:
static const uint32_t ByteSendTimeUs = 20; // us it takes to send a single pixel element at 400khz speed
static const uint32_t UartBaud = 1600000; // 400mhz, 4 serial bytes per NeoByte
static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update
};
// NeoEsp8266UartSpeedApa106 contains the timing constant used to get NeoPixelBus running for Apa106
// Pulse cycle = 1.71 = 1.368 longer than normal, 0.731 slower, NeoEsp8266UartSpeedApa1066
class NeoEsp8266UartSpeedApa106
{
public:
static const uint32_t ByteSendTimeUs = 14; // us it takes to send a single pixel element at 400khz speed
static const uint32_t UartBaud = 2339181; // APA106 pulse cycle of 1.71us, 4 serial bytes per NeoByte
static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update
};
// NeoEsp8266UartMethodBase is a light shell arround NeoEsp8266Uart or NeoEsp8266AsyncUart that
// implements the methods needed to operate as a NeoPixelBus method.
template<typename T_SPEED, typename T_BASE>
class NeoEsp8266UartMethodBase: public T_BASE
{
public:
NeoEsp8266UartMethodBase(uint16_t pixelCount, size_t elementSize)
: T_BASE(pixelCount, elementSize)
{
}
NeoEsp8266UartMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize)
: T_BASE(pixelCount, elementSize)
{
}
bool IsReadyToUpdate() const
{
uint32_t delta = micros() - this->_startTime;
return delta >= getPixelTime() + T_SPEED::ResetTimeUs;
}
void Initialize()
{
this->InitializeUart(T_SPEED::UartBaud);
// Inverting logic levels can generate a phantom bit in the led strip bus
// We need to delay 50+ microseconds the output stream to force a data
// latch and discard this bit. Otherwise, that bit would be prepended to
// the first frame corrupting it.
this->_startTime = micros() - getPixelTime();
}
void Update(bool maintainBufferConsistency)
{
// Data latch = 50+ microsecond pause in the output stream. Rather than
// put a delay at the end of the function, the ending time is noted and
// the function will simply hold off (if needed) on issuing the
// subsequent round of data until the latch time has elapsed. This
// allows the mainline code to start generating the next frame of data
// rather than stalling for the latch.
while (!this->IsReadyToUpdate())
{
yield();
}
this->UpdateUart(maintainBufferConsistency);
}
uint8_t* getPixels() const
{
return this->_pixels;
};
size_t getPixelsSize() const
{
return this->_sizePixels;
};
private:
uint32_t getPixelTime() const
{
return (T_SPEED::ByteSendTimeUs * this->_sizePixels);
};
};
// uart 0
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0400KbpsMethod;
typedef NeoEsp8266Uart0Ws2812xMethod NeoEsp8266Uart0Ws2813Method;
typedef NeoEsp8266Uart0800KbpsMethod NeoEsp8266Uart0Ws2812Method;
typedef NeoEsp8266Uart0Sk6812Method NeoEsp8266Uart0Lc8812Method;
// uart 1
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1400KbpsMethod;
typedef NeoEsp8266Uart1Ws2812xMethod NeoEsp8266Uart1Ws2813Method;
typedef NeoEsp8266Uart1800KbpsMethod NeoEsp8266Uart1Ws2812Method;
typedef NeoEsp8266Uart1Sk6812Method NeoEsp8266Uart1Lc8812Method;
// uart 0 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0400KbpsMethod;
typedef NeoEsp8266AsyncUart0Ws2812xMethod NeoEsp8266AsyncUart0Ws2813Method;
typedef NeoEsp8266AsyncUart0800KbpsMethod NeoEsp8266AsyncUart0Ws2812Method;
typedef NeoEsp8266AsyncUart0Sk6812Method NeoEsp8266AsyncUart0Lc8812Method;
// uart 1 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1400KbpsMethod;
typedef NeoEsp8266AsyncUart1Ws2812xMethod NeoEsp8266AsyncUart1Ws2813Method;
typedef NeoEsp8266AsyncUart1800KbpsMethod NeoEsp8266AsyncUart1Ws2812Method;
typedef NeoEsp8266AsyncUart1Sk6812Method NeoEsp8266AsyncUart1Lc8812Method;
#endif

View File

@ -1,195 +0,0 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp8266 and Esp32
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
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
// ESP32 doesn't define ICACHE_RAM_ATTR
#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR IRAM_ATTR
#endif
// for esp8266, due to linker overriding the ICACHE_RAM_ATTR for cpp files, these methods are
// moved into a C file so the attribute will be applied correctly
// >> this may have been fixed and is no longer a requirement <<
extern "C" void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin);
extern "C" void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin);
class NeoEspBitBangSpeedWs2812x
{
public:
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
bitbang_send_pixels_800(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 300;
};
class NeoEspBitBangSpeedSk6812
{
public:
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
bitbang_send_pixels_800(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 80;
};
class NeoEspBitBangSpeed800Kbps
{
public:
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
bitbang_send_pixels_800(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 50;
};
class NeoEspBitBangSpeed400Kbps
{
public:
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
bitbang_send_pixels_400(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEED> class NeoEspBitBangMethodBase
{
public:
NeoEspBitBangMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) :
_pin(pin)
{
pinMode(pin, OUTPUT);
_sizePixels = pixelCount * elementSize;
_pixels = (uint8_t*)malloc(_sizePixels);
memset(_pixels, 0, _sizePixels);
}
~NeoEspBitBangMethodBase()
{
pinMode(_pin, INPUT);
free(_pixels);
}
bool IsReadyToUpdate() const
{
uint32_t delta = micros() - _endTime;
return (delta >= T_SPEED::ResetTimeUs);
}
void Initialize()
{
digitalWrite(_pin, LOW);
_endTime = micros();
}
void Update(bool)
{
// Data latch = 50+ microsecond pause in the output stream. Rather than
// put a delay at the end of the function, the ending time is noted and
// the function will simply hold off (if needed) on issuing the
// subsequent round of data until the latch time has elapsed. This
// allows the mainline code to start generating the next frame of data
// rather than stalling for the latch.
while (!IsReadyToUpdate())
{
yield(); // allows for system yield if needed
}
// Need 100% focus on instruction timing
#if defined(ARDUINO_ARCH_ESP32)
delay(1); // required
portMUX_TYPE updateMux = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&updateMux);
#else
noInterrupts();
#endif
T_SPEED::send_pixels(_pixels, _pixels + _sizePixels, _pin);
#if defined(ARDUINO_ARCH_ESP32)
portEXIT_CRITICAL(&updateMux);
#else
interrupts();
#endif
// save EOD time for latch on next call
_endTime = micros();
}
uint8_t* getPixels() const
{
return _pixels;
};
size_t getPixelsSize() const
{
return _sizePixels;
};
private:
uint32_t _endTime; // Latch timing reference
size_t _sizePixels; // Size of '_pixels' buffer below
uint8_t* _pixels; // Holds LED color values
uint8_t _pin; // output pin number
};
#if defined(ARDUINO_ARCH_ESP32)
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x> NeoEsp32BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812> NeoEsp32BitBangSk6812Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps> NeoEsp32BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps> NeoEsp32BitBang400KbpsMethod;
typedef NeoEsp32BitBangWs2812xMethod NeoEsp32BitBangWs2813Method;
typedef NeoEsp32BitBang800KbpsMethod NeoEsp32BitBangWs2812Method;
typedef NeoEsp32BitBangSk6812Method NeoEsp32BitBangLc8812Method;
typedef NeoEsp32BitBang400KbpsMethod NeoEsp32BitBangApa106Method;
#else
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x> NeoEsp8266BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812> NeoEsp8266BitBangSk6812Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps> NeoEsp8266BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps> NeoEsp8266BitBang400KbpsMethod;
typedef NeoEsp8266BitBangWs2812xMethod NeoEsp8266BitBangWs2813Method;
typedef NeoEsp8266BitBang800KbpsMethod NeoEsp8266BitBangWs2812Method;
typedef NeoEsp8266BitBangSk6812Method NeoEsp8266BitBangLc8812Method;
typedef NeoEsp8266BitBang400KbpsMethod NeoEsp8266BitBangApa106Method;
#endif
// ESP bitbang doesn't have defaults and should avoided except for testing
#endif

View File

@ -1,169 +0,0 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp8266 and Esp32.
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/>.
-------------------------------------------------------------------------*/
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#include <Arduino.h>
#if defined(ARDUINO_ARCH_ESP8266)
#include <eagle_soc.h>
#endif
// ESP32 doesn't define ICACHE_RAM_ATTR
#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR IRAM_ATTR
#endif
static uint32_t _getCycleCount(void) __attribute__((always_inline));
static inline uint32_t _getCycleCount(void)
{
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
return ccount;
}
#define CYCLES_800_T0H (F_CPU / 2500000) // 0.4us
#define CYCLES_800_T1H (F_CPU / 1250000) // 0.8us
#define CYCLES_800 (F_CPU / 800000) // 1.25us per bit
#define CYCLES_400_T0H (F_CPU / 2000000)
#define CYCLES_400_T1H (F_CPU / 833333)
#define CYCLES_400 (F_CPU / 400000)
void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
const uint32_t pinRegister = _BV(pin);
uint8_t mask = 0x80;
uint8_t subpix = *pixels++;
uint32_t cyclesStart = 0; // trigger emediately
uint32_t cyclesNext = 0;
for (;;)
{
// do the checks here while we are waiting on time to pass
uint32_t cyclesBit = CYCLES_800_T0H;
if (subpix & mask)
{
cyclesBit = CYCLES_800_T1H;
}
// after we have done as much work as needed for this next bit
// now wait for the HIGH
while (((cyclesStart = _getCycleCount()) - cyclesNext) < CYCLES_800);
// set high
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
#endif
// wait for the LOW
while ((_getCycleCount() - cyclesStart) < cyclesBit);
// set low
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1tc = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
#endif
cyclesNext = cyclesStart;
// next bit
mask >>= 1;
if (mask == 0)
{
// no more bits to send in this byte
// check for another byte
if (pixels >= end)
{
// no more bytes to send so stop
break;
}
// reset mask to first bit and get the next byte
mask = 0x80;
subpix = *pixels++;
}
}
}
void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
const uint32_t pinRegister = _BV(pin);
uint8_t mask = 0x80;
uint8_t subpix = *pixels++;
uint32_t cyclesStart = 0; // trigger emediately
uint32_t cyclesNext = 0;
for (;;)
{
// do the checks here while we are waiting on time to pass
uint32_t cyclesBit = CYCLES_400_T0H;
if (subpix & mask)
{
cyclesBit = CYCLES_400_T1H;
}
// after we have done as much work as needed for this next bit
// now wait for the HIGH
while (((cyclesStart = _getCycleCount()) - cyclesNext) < CYCLES_400);
// set high
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
#endif
// wait for the LOW
while ((_getCycleCount() - cyclesStart) < cyclesBit);
// set low
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1tc = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
#endif
cyclesNext = cyclesStart;
// next bit
mask >>= 1;
if (mask == 0)
{
// no more bits to send in this byte
// check for another byte
if (pixels >= end)
{
// no more bytes to send so stop
break;
}
// reset mask to first bit and get the next byte
mask = 0x80;
subpix = *pixels++;
}
}
}
#endif

View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: [makuna]
custom: ["https://paypal.me/MakunaGithub"]

View File

@ -0,0 +1,14 @@
---
name: All others
about: If your issue doesn't fit the other two, this will guide you to support.
title: "[DELETE ME]"
labels: NOT AN ISSUE
assignees: ''
---
### STOP
If you are seeking support, then please use the gitter channel by following this link.
[NeoPixelBus Gitter Channel](https://gitter.im/Makuna/NeoPixelBus)
If you submit issues that are not traceable bugs or feature requests, it will get closed and you will be directed to the gitter channel.

View File

@ -1,6 +1,9 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---

View File

@ -1,6 +1,9 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---

View File

@ -4,15 +4,13 @@
Arduino NeoPixel library
A library to control one wire protocol RGB and RGBW leds like SK6812, WS2811, WS2812 and WS2813 that are commonly refered to as NeoPixels and two wire protocol RGB like APA102 commonly refered to as DotStars.
A library to control one wire protocol RGB and RGBW leds like APA106, SK6812, WS2811, WS2812 and WS2813 that are commonly refered to as NeoPixels and two wire protocol RGB like Lpd8806, APA102 and SK9822 commonly refered to as DotStars.
Supports most Arduino platforms.
This is the most functional library for the Esp8266 as it provides solutions for all Esp8266 module types even when WiFi is used.
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 jump on Gitter and ask away.
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 bugs, make sure there isn't an active issue and then create one.

View File

@ -53,7 +53,7 @@ NeoPixelAnimator animations(PixelCount, NEO_CENTISECONDS);
// NEO_DECASECONDS 10000 // ~7.5 days, 10 second updates
//
#ifdef ARDUINO_ARCH_AVR
#if defined(NEOPIXEBUS_NO_STL)
// for AVR, you need to manage the state due to lack of STL/compiler support
// for Esp8266 you can define the function using a lambda and state is created for you
// see below for an example
@ -158,7 +158,7 @@ void SetupAnimationSet()
break;
}
#ifdef ARDUINO_ARCH_AVR
#if defined(NEOPIXEBUS_NO_STL)
// each animation starts with the color that was present
animationState[pixel].StartingColor = originalColor;
// and ends with a random color

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -0,0 +1,36 @@
// NeoSegmentBus
// This example will demonstrate using the NeoSegmentBus which provides support for a
// seven segment LED digit driven by three WS2811; connected in series with other digits
//
// See https://shop.idlehandsdev.com/products/addressable-7-segment-display for a hardware example
//
// This example will print the string "3.14" and then rotate it through the available digits
//
#include <NeoPixelSegmentBus.h>
const uint16_t DigitCount = 4; // Max Digits, not segments, not pixels
const uint8_t BusPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
#define brightness 128
NeoPixelSegmentBus<SevenSegmentFeature, NeoWs2811Method> strip(DigitCount, BusPin);
void setup()
{
strip.Begin();
strip.Show(); // clears all digits by default
delay(500);
strip.SetString(0, "3.14", brightness);
strip.Show();
}
void loop()
{
delay(2000);
strip.RotateLeft(1);
strip.Show();
}

View File

@ -0,0 +1,144 @@
// NeoSegmentBus
// This example will demonstrate using the NeoSegmentBus which provides support for a
// seven segment LED digit driven by three WS2811; connected in series with other digits
//
// See https://shop.idlehandsdev.com/products/addressable-7-segment-display for a hardware example
//
// This example will print current seconds since start of the Arduino
// with a digit animating a circling path for each second
//
#include <NeoPixelSegmentBus.h>
#include <NeoPixelAnimator.h>
const uint16_t DigitCount = 5; // Max Digits, not segments, not pixels
const uint8_t BusPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
const uint16_t CycleDigit = 0;
const uint16_t SecondsDigit = 1;
#define brightness 128
NeoPixelSegmentBus<SevenSegmentFeature, NeoWs2811Method> strip(DigitCount, BusPin);
enum Animation
{
Animation_Cycle, // animation for the cycle indicator
Animation_Fade, // animation for fade of seconds
Animation_COUNT
};
NeoPixelAnimator animations(Animation_COUNT);
void CycleAnimation(const AnimationParam& param)
{
// calculate which segment should be on using the animation progress
uint8_t bitfield = 1 << (uint8_t)(param.progress * LedSegment_F);
// instant a digit with that segment on
SevenSegDigit digit(bitfield, brightness);
// apply it to the strip
strip.SetPixelColor(CycleDigit, digit);
}
// for the animation of fading the new number in, we use
// two digit DIBs (Device Independant Bitmaps) of SevenSegDigit to blend with;
// each sized one less than the strip due to the first is a used for the cycle
// animation.
typedef NeoDib<SevenSegDigit> SevenSegDib;
SevenSegDib StartingDigits(DigitCount - 1);
SevenSegDib EndingDigits(DigitCount - 1);
// shader class that will do the "string" blending
//
class DigitBlendShader
{
public:
// this shader always renders and doesn't track a dirty state
bool IsDirty() const
{
return true;
}
void ResetDirty()
{
}
SevenSegDigit Apply(uint16_t indexDigit, SevenSegDigit digit)
{
// since we call EndingDigits.Render below, the digit argument is
// from the EndingDigits so no need to call GetPixelColor to get it
// create a digit that is a blend between the last seconds
// value and the next seconds value using the BlendAmount
SevenSegDigit blendDigit = SevenSegDigit::LinearBlend(
StartingDigits.GetPixelColor(indexDigit),
digit,
BlendAmount);
return blendDigit;
}
float BlendAmount;
};
// the instance of our shader class
DigitBlendShader blendShader;
void FadeAnimation(const AnimationParam& param)
{
// set the shader property BlendAmount to the animation progress
blendShader.BlendAmount = param.progress;
// apply it to the strip at the SecondsDigit location
EndingDigits.Render<SevenSegmentFeature, DigitBlendShader>(strip,
blendShader,
SecondsDigit);
}
uint32_t lastSeconds;
void setup()
{
lastSeconds = millis() / 1000;
strip.Begin();
strip.Show();
// init animation Dibs as cleared
StartingDigits.ClearTo(0);
EndingDigits.ClearTo(0);
}
void loop()
{
uint32_t seconds = millis() / 1000;
// when the seconds change, start animations for the update
//
if (seconds != lastSeconds)
{
// copy last animation ending digits as starting digits
StartingDigits = EndingDigits;
// format and display new value in ending digits dib
String display(seconds);
SevenSegDigit::SetString<SevenSegDib>(EndingDigits,
0,
display.c_str(),
brightness);
// start the seconds fade animation
animations.StartAnimation(Animation_Fade, 1000, FadeAnimation);
// start the cycle animation for the next second
animations.StartAnimation(Animation_Cycle, 1000, CycleAnimation);
lastSeconds = seconds;
}
if (animations.IsAnimating())
{
// the normal loop just needs these two to run the active animations
animations.UpdateAnimations();
strip.Show();
}
}

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

@ -0,0 +1,539 @@
#######################################
# Syntax Coloring Map NeoPixelBus
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
NeoPixelBus KEYWORD1
NeoPixelSegmentBus KEYWORD1
RgbwColor KEYWORD1
RgbColor KEYWORD1
HslColor KEYWORD1
HsbColor KEYWORD1
HtmlColor KEYWORD1
NeoNoSettings KEYWORD1
NeoTm1814Settings KEYWORD1
NeoGrbFeature KEYWORD1
NeoGrbwFeature KEYWORD1
NeoRgbwFeature KEYWORD1
NeoRgbFeature KEYWORD1
NeoBrgFeature KEYWORD1
NeoRbgFeature KEYWORD1
NeoWrgbTm1814Feature KEYWORD1
DotStarBgrFeature KEYWORD1
DotStarLbgrFeature KEYWORD1
Lpd8806GrbFeature KEYWORD1
P9813BgrFeature KEYWORD1
SevenSegmentFeature KEYWORD1
Neo800KbpsMethod KEYWORD1
Neo400KbpsMethod KEYWORD1
NeoWs2813Method KEYWORD1
NeoWs2812xMethod KEYWORD1
NeoWs2812Method KEYWORD1
NeoWs2811Method KEYWORD1
NeoSk6812Method KEYWORD1
NeoTm1814Method KEYWORD1
NeoLc8812Method KEYWORD1
NeoApa106Method KEYWORD1
Neo800KbpsInvertedMethod KEYWORD1
Neo400KbpsInvertedMethod KEYWORD1
NeoWs2813InvertedMethod KEYWORD1
NeoWs2812xInvertedMethod KEYWORD1
NeoWs2812InvertedMethod KEYWORD1
NeoWs2811InvertedMethod KEYWORD1
NeoSk6812InvertedMethod KEYWORD1
NeoTm1814InvertedMethod KEYWORD1
NeoLc8812InvertedMethod KEYWORD1
NeoApa106InvertedMethod KEYWORD1
NeoEsp8266DmaWs2812xMethod KEYWORD1
NeoEsp8266DmaSk6812Method KEYWORD1
NeoEsp8266DmaTm1814Method KEYWORD1
NeoEsp8266DmaApa106Method KEYWORD1
NeoEsp8266Dma800KbpsMethod KEYWORD1
NeoEsp8266Dma400KbpsMethod KEYWORD1
NeoEsp8266DmaInvertedWs2812xMethod KEYWORD1
NeoEsp8266DmaInvertedSk6812Method KEYWORD1
NeoEsp8266DmaInvertedTm1814Method KEYWORD1
NeoEsp8266DmaInvertedApa106Method KEYWORD1
NeoEsp8266DmaInverted800KbpsMethod KEYWORD1
NeoEsp8266DmaInverted400KbpsMethod KEYWORD1
NeoEsp8266Uart0Ws2813Method KEYWORD1
NeoEsp8266Uart0Ws2812xMethod KEYWORD1
NeoEsp8266Uart0Ws2812Method KEYWORD1
NeoEsp8266Uart0Ws2811Method KEYWORD1
NeoEsp8266Uart0Sk6812Method KEYWORD1
NeoEsp8266Uart0Tm1814Method KEYWORD1
NeoEsp8266Uart0Lc8812Method KEYWORD1
NeoEsp8266Uart0Apa106Method KEYWORD1
NeoEsp8266Uart0800KbpsMethod KEYWORD1
NeoEsp8266Uart0400KbpsMethod KEYWORD1
NeoEsp8266AsyncUart0Ws2813Method KEYWORD1
NeoEsp8266AsyncUart0Ws2812xMethod KEYWORD1
NeoEsp8266AsyncUart0Ws2812Method KEYWORD1
NeoEsp8266AsyncUart0Ws2811Method KEYWORD1
NeoEsp8266AsyncUart0Sk6812Method KEYWORD1
NeoEsp8266AsyncUart0Tm1814Method KEYWORD1
NeoEsp8266AsyncUart0Lc8812Method KEYWORD1
NeoEsp8266AsyncUart0Apa106Method KEYWORD1
NeoEsp8266AsyncUart0800KbpsMethod KEYWORD1
NeoEsp8266AsyncUart0400KbpsMethod KEYWORD1
NeoEsp8266Uart1Ws2813Method KEYWORD1
NeoEsp8266Uart1Ws2812xMethod KEYWORD1
NeoEsp8266Uart1Ws2812Method KEYWORD1
NeoEsp8266Uart1Ws2811Method KEYWORD1
NeoEsp8266Uart1Sk6812Method KEYWORD1
NeoEsp8266Uart1Tm1814 KEYWORD1
NeoEsp8266Uart1Lc8812Method KEYWORD1
NeoEsp8266Uart1Apa106Method KEYWORD1
NeoEsp8266Uart1800KbpsMethod KEYWORD1
NeoEsp8266Uart1400KbpsMethod KEYWORD1
NeoEsp8266AsyncUart1Ws2813Method KEYWORD1
NeoEsp8266AsyncUart1Ws2812xMethod KEYWORD1
NeoEsp8266AsyncUart1Ws2812Method KEYWORD1
NeoEsp8266AsyncUart1Ws2811Method KEYWORD1
NeoEsp8266AsyncUart1Sk6812Method KEYWORD1
NeoEsp8266AsyncUart1Tm1814 KEYWORD1
NeoEsp8266AsyncUart1Lc8812Method KEYWORD1
NeoEsp8266AsyncUart1Apa106Method KEYWORD1
NeoEsp8266AsyncUart1800KbpsMethod KEYWORD1
NeoEsp8266AsyncUart1400KbpsMethod KEYWORD1
NeoEsp8266Uart0Ws2813InvertedMethod KEYWORD1
NeoEsp8266Uart0Ws2812xInvertedMethod KEYWORD1
NeoEsp8266Uart0Ws2812InvertedMethod KEYWORD1
NeoEsp8266Uart0Ws2811InvertedMethod KEYWORD1
NeoEsp8266Uart0Sk6812InvertedMethod KEYWORD1
NeoEsp8266Uart0Tm1814InvertedMethod KEYWORD1
NeoEsp8266Uart0Lc8812InvertedMethod KEYWORD1
NeoEsp8266Uart0Apa106InvertedMethod KEYWORD1
NeoEsp8266Uart0800KbpsInvertedMethod KEYWORD1
NeoEsp8266Uart0400KbpsInvertedMethod KEYWORD1
NeoEsp8266AsyncUart0Ws2813InvertedMethod KEYWORD1
NeoEsp8266AsyncUart0Ws2812xInvertedMethod KEYWORD1
NeoEsp8266AsyncUart0Ws2812InvertedMethod KEYWORD1
NeoEsp8266AsyncUart0Ws2811InvertedMethod KEYWORD1
NeoEsp8266AsyncUart0Sk6812InvertedMethod KEYWORD1
NeoEsp8266AsyncUart0Tm1814InvertedMethod KEYWORD1
NeoEsp8266AsyncUart0Lc8812InvertedMethod KEYWORD1
NeoEsp8266AsyncUart0Apa106InvertedMethod KEYWORD1
NeoEsp8266AsyncUart0800KbpsInvertedMethod KEYWORD1
NeoEsp8266AsyncUart0400KbpsInvertedMethod KEYWORD1
NeoEsp8266Uart1Ws2813InvertedMethod KEYWORD1
NeoEsp8266Uart1Ws2812xInvertedMethod KEYWORD1
NeoEsp8266Uart1Ws2812InvertedMethod KEYWORD1
NeoEsp8266Uart1Ws2811InvertedMethod KEYWORD1
NeoEsp8266Uart1Sk6812InvertedMethod KEYWORD1
NeoEsp8266Uart1Tm1814InvertedMethod KEYWORD1
NeoEsp8266Uart1Lc8812InvertedMethod KEYWORD1
NeoEsp8266Uart1Apa106InvertedMethod KEYWORD1
NeoEsp8266Uart1800KbpsInvertedMethod KEYWORD1
NeoEsp8266Uart1400KbpsInvertedMethod KEYWORD1
NeoEsp8266AsyncUart1Ws2813InvertedMethod KEYWORD1
NeoEsp8266AsyncUart1Ws2812xInvertedMethod KEYWORD1
NeoEsp8266AsyncUart1Ws2812InvertedMethod KEYWORD1
NeoEsp8266AsyncUart1Ws2811InvertedMethod KEYWORD1
NeoEsp8266AsyncUart1Sk6812InvertedMethod KEYWORD1
NeoEsp8266AsyncUart1Tm1814InvertedMethod KEYWORD1
NeoEsp8266AsyncUart1Lc8812InvertedMethod KEYWORD1
NeoEsp8266AsyncUart1Apa106InvertedMethod KEYWORD1
NeoEsp8266AsyncUart1800KbpsInvertedMethod KEYWORD1
NeoEsp8266AsyncUart1400KbpsInvertedMethod KEYWORD1
NeoEsp8266BitBangWs2813Method KEYWORD1
NeoEsp8266BitBangWs2812xMethod KEYWORD1
NeoEsp8266BitBangWs2812Method KEYWORD1
NeoEsp8266BitBangWs2811Method KEYWORD1
NeoEsp8266BitBangSk6812Method KEYWORD1
NeoEsp8266BitBangTm1814Method KEYWORD1
NeoEsp8266BitBangLc8812Method KEYWORD1
NeoEsp8266BitBangApa106Method KEYWORD1
NeoEsp8266BitBang800KbpsMethod KEYWORD1
NeoEsp8266BitBang400KbpsMethod KEYWORD1
NeoEsp8266BitBangWs2813InvertedMethod KEYWORD1
NeoEsp8266BitBangWs2812xInvertedMethod KEYWORD1
NeoEsp8266BitBangWs2812InvertedMethod KEYWORD1
NeoEsp8266BitBangWs2811InvertedMethod KEYWORD1
NeoEsp8266BitBangSk6812InvertedMethod KEYWORD1
NeoEsp8266BitBangTm1814InvertedMethod KEYWORD1
NeoEsp8266BitBangLc8812InvertedMethod KEYWORD1
NeoEsp8266BitBangApa106InvertedMethod KEYWORD1
NeoEsp8266BitBang800KbpsInvertedMethod KEYWORD1
NeoEsp8266BitBang400KbpsInvertedMethod KEYWORD1
NeoEsp32I2s0Ws2812xMethod KEYWORD1
NeoEsp32I2s0Sk6812Method KEYWORD1
NeoEsp32I2s0Tm1814Method KEYWORD1
NeoEsp32I2s0800KbpsMethod KEYWORD1
NeoEsp32I2s0400KbpsMethod KEYWORD1
NeoEsp32I2s0Apa106Method KEYWORD1
NeoEsp32I2s1Ws2812xMethod KEYWORD1
NeoEsp32I2s1Sk6812Method KEYWORD1
NeoEsp32I2s1Tm1814Method KEYWORD1
NeoEsp32I2s1800KbpsMethod KEYWORD1
NeoEsp32I2s1400KbpsMethod KEYWORD1
NeoEsp32I2s1Apa106Method KEYWORD1
NeoEsp32I2s0Ws2812xInvertedMethod KEYWORD1
NeoEsp32I2s0Sk6812InvertedMethod KEYWORD1
NeoEsp32I2s0Tm1814InvertedMethod KEYWORD1
NeoEsp32I2s0800KbpsInvertedMethod KEYWORD1
NeoEsp32I2s0400KbpsInvertedMethod KEYWORD1
NeoEsp32I2s0Apa106InvertedMethod KEYWORD1
NeoEsp32I2s1Ws2812xInvertedMethod KEYWORD1
NeoEsp32I2s1Sk6812InvertedMethod KEYWORD1
NeoEsp32I2s1Tm1814InvertedMethod KEYWORD1
NeoEsp32I2s1800KbpsInvertedMethod KEYWORD1
NeoEsp32I2s1400KbpsInvertedMethod KEYWORD1
NeoEsp32I2s1Apa106InvertedMethod KEYWORD1
NeoEsp32Rmt0Ws2811Method KEYWORD1
NeoEsp32Rmt0Ws2812xMethod KEYWORD1
NeoEsp32Rmt0Sk6812Method KEYWORD1
NeoEsp32Rmt0Tm1814Method KEYWORD1
NeoEsp32Rmt0Apa106Method KEYWORD1
NeoEsp32Rmt0800KbpsMethod KEYWORD1
NeoEsp32Rmt0400KbpsMethod KEYWORD1
NeoEsp32Rmt1Ws2811Method KEYWORD1
NeoEsp32Rmt1Ws2812xMethod KEYWORD1
NeoEsp32Rmt1Sk6812Method KEYWORD1
NeoEsp32Rmt1Tm1814Method KEYWORD1
NeoEsp32Rmt1Apa106Method KEYWORD1
NeoEsp32Rmt1800KbpsMethod KEYWORD1
NeoEsp32Rmt1400KbpsMethod KEYWORD1
NeoEsp32Rmt2Ws2811Method KEYWORD1
NeoEsp32Rmt2Ws2812xMethod KEYWORD1
NeoEsp32Rmt2Sk6812Method KEYWORD1
NeoEsp32Rmt2Tm1814Method KEYWORD1
NeoEsp32Rmt2Apa106Method KEYWORD1
NeoEsp32Rmt2800KbpsMethod KEYWORD1
NeoEsp32Rmt2400KbpsMethod KEYWORD1
NeoEsp32Rmt3Ws2811Method KEYWORD1
NeoEsp32Rmt3Ws2812xMethod KEYWORD1
NeoEsp32Rmt3Sk6812Method KEYWORD1
NeoEsp32Rmt3Tm1814Method KEYWORD1
NeoEsp32Rmt3Apa106Method KEYWORD1
NeoEsp32Rmt3800KbpsMethod KEYWORD1
NeoEsp32Rmt3400KbpsMethod KEYWORD1
NeoEsp32Rmt4Ws2811Method KEYWORD1
NeoEsp32Rmt4Ws2812xMethod KEYWORD1
NeoEsp32Rmt4Sk6812Method KEYWORD1
NeoEsp32Rmt4Tm1814Method KEYWORD1
NeoEsp32Rmt4Apa106Method KEYWORD1
NeoEsp32Rmt4800KbpsMethod KEYWORD1
NeoEsp32Rmt4400KbpsMethod KEYWORD1
NeoEsp32Rmt5Ws2811Method KEYWORD1
NeoEsp32Rmt5Ws2812xMethod KEYWORD1
NeoEsp32Rmt5Sk6812Method KEYWORD1
NeoEsp32Rmt5Tm1814Method KEYWORD1
NeoEsp32Rmt5Apa106Method KEYWORD1
NeoEsp32Rmt5800KbpsMethod KEYWORD1
NeoEsp32Rmt5400KbpsMethod KEYWORD1
NeoEsp32Rmt6Ws2811Method KEYWORD1
NeoEsp32Rmt6Ws2812xMethod KEYWORD1
NeoEsp32Rmt6Sk6812Method KEYWORD1
NeoEsp32Rmt6Tm1814Method KEYWORD1
NeoEsp32Rmt6Apa106Method KEYWORD1
NeoEsp32Rmt6800KbpsMethod KEYWORD1
NeoEsp32Rmt6400KbpsMethod KEYWORD1
NeoEsp32Rmt7Ws2811Method KEYWORD1
NeoEsp32Rmt7Ws2812xMethod KEYWORD1
NeoEsp32Rmt7Sk6812Method KEYWORD1
NeoEsp32Rmt7Tm1814Method KEYWORD1
NeoEsp32Rmt7Apa106Method KEYWORD1
NeoEsp32Rmt7800KbpsMethod KEYWORD1
NeoEsp32Rmt7400KbpsMethod KEYWORD1
NeoEsp32Rmt0Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt0Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt0Sk6812InvertedMethod KEYWORD1
NeoEsp32Rmt0Tm1814InvertedMethod KEYWORD1
NeoEsp32Rmt0Apa106InvertedMethod KEYWORD1
NeoEsp32Rmt0800KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt0400KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt1Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt1Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt1Sk6812InvertedMethod KEYWORD1
NeoEsp32Rmt1Tm1814InvertedMethod KEYWORD1
NeoEsp32Rmt1Apa106InvertedMethod KEYWORD1
NeoEsp32Rmt1800KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt1400KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt2Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt2Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt2Sk6812InvertedMethod KEYWORD1
NeoEsp32Rmt2Tm1814InvertedMethod KEYWORD1
NeoEsp32Rmt2Apa106InvertedMethod KEYWORD1
NeoEsp32Rmt2800KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt2400KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt3Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt3Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt3Sk6812InvertedMethod KEYWORD1
NeoEsp32Rmt3Tm1814InvertedMethod KEYWORD1
NeoEsp32Rmt3Apa106InvertedMethod KEYWORD1
NeoEsp32Rmt3800KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt3400KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt4Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt4Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt4Sk6812InvertedMethod KEYWORD1
NeoEsp32Rmt4Tm1814InvertedMethod KEYWORD1
NeoEsp32Rmt4Apa106InvertedMethod KEYWORD1
NeoEsp32Rmt4800KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt4400KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt5Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt5Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt5Sk6812InvertedMethod KEYWORD1
NeoEsp32Rmt5Tm1814InvertedMethod KEYWORD1
NeoEsp32Rmt5Apa106InvertedMethod KEYWORD1
NeoEsp32Rmt5800KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt5400KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt6Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt6Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt6Sk6812InvertedMethod KEYWORD1
NeoEsp32Rmt6Tm1814InvertedMethod KEYWORD1
NeoEsp32Rmt6Apa106InvertedMethod KEYWORD1
NeoEsp32Rmt6800KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt6400KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt7Ws2811InvertedMethod KEYWORD1
NeoEsp32Rmt7Ws2812xInvertedMethod KEYWORD1
NeoEsp32Rmt7Sk6812InvertedMethod KEYWORD1
NeoEsp32Rmt7Tm1814InvertedMethod KEYWORD1
NeoEsp32Rmt7Apa106InvertedMethod KEYWORD1
NeoEsp32Rmt7800KbpsInvertedMethod KEYWORD1
NeoEsp32Rmt7400KbpsInvertedMethod KEYWORD1
NeoEsp32BitBangWs2813Method KEYWORD1
NeoEsp32BitBangWs2812xMethod KEYWORD1
NeoEsp32BitBangWs2812Method KEYWORD1
NeoEsp32BitBangWs2811Method KEYWORD1
NeoEsp32BitBangSk6812Method KEYWORD1
NeoEsp32BitBangTm1814Method KEYWORD1
NeoEsp32BitBangLc8812Method KEYWORD1
NeoEsp32BitBangApa106Method KEYWORD1
NeoEsp32BitBang800KbpsMethod KEYWORD1
NeoEsp32BitBang400KbpsMethod KEYWORD1
NeoEsp32BitBangWs2813InvertedMethod KEYWORD1
NeoEsp32BitBangWs2812xInvertedMethod KEYWORD1
NeoEsp32BitBangWs2812InvertedMethod KEYWORD1
NeoEsp32BitBangWs2811InvertedMethod KEYWORD1
NeoEsp32BitBangSk6812InvertedMethod KEYWORD1
NeoEsp32BitBangTm1814InvertedMethod KEYWORD1
NeoEsp32BitBangLc8812InvertedMethod KEYWORD1
NeoEsp32BitBangApa106InvertedMethod KEYWORD1
NeoEsp32BitBang800KbpsInvertedMethod KEYWORD1
NeoEsp32BitBang400KbpsInvertedMethod KEYWORD1
NeoNrf52xPwm0Ws2812xMethod KEYWORD1
NeoNrf52xPwm0Sk6812Method KEYWORD1
NeoNrf52xPwm0Tm1814Method KEYWORD1
NeoNrf52xPwm0800KbpsMethod KEYWORD1
NeoNrf52xPwm0400KbpsMethod KEYWORD1
NeoNrf52xPwm0Apa106Method KEYWORD1
NeoNrf52xPwm1Ws2812xMethod KEYWORD1
NeoNrf52xPwm1Sk6812Method KEYWORD1
NeoNrf52xPwm1Tm1814Method KEYWORD1
NeoNrf52xPwm1800KbpsMethod KEYWORD1
NeoNrf52xPwm1400KbpsMethod KEYWORD1
NeoNrf52xPwm1Apa106Method KEYWORD1
NeoNrf52xPwm2Ws2812xMethod KEYWORD1
NeoNrf52xPwm2Sk6812Method KEYWORD1
NeoNrf52xPwm2Tm1814Method KEYWORD1
NeoNrf52xPwm2800KbpsMethod KEYWORD1
NeoNrf52xPwm2400KbpsMethod KEYWORD1
NeoNrf52xPwm2Apa106Method KEYWORD1
NeoNrf52xPwm3Ws2812xMethod KEYWORD1
NeoNrf52xPwm3Sk6812Method KEYWORD1
NeoNrf52xPwm3Tm1814Method KEYWORD1
NeoNrf52xPwm3800KbpsMethod KEYWORD1
NeoNrf52xPwm3400KbpsMethod KEYWORD1
NeoNrf52xPwm3Apa106Method KEYWORD1
NeoNrf52xPwm0Ws2812xInvertedMethod KEYWORD1
NeoNrf52xPwm0Sk6812InvertedMethod KEYWORD1
NeoNrf52xPwm0Tm1814InvertedMethod KEYWORD1
NeoNrf52xPwm0800KbpsInvertedMethod KEYWORD1
NeoNrf52xPwm0400KbpsInvertedMethod KEYWORD1
NeoNrf52xPwm0Apa106InvertedMethod KEYWORD1
NeoNrf52xPwm1Ws2812xInvertedMethod KEYWORD1
NeoNrf52xPwm1Sk6812InvertedMethod KEYWORD1
NeoNrf52xPwm1Tm1814InvertedMethod KEYWORD1
NeoNrf52xPwm1800KbpsInvertedMethod KEYWORD1
NeoNrf52xPwm1400KbpsInvertedMethod KEYWORD1
NeoNrf52xPwm1Apa106InvertedMethod KEYWORD1
NeoNrf52xPwm2Ws2812xInvertedMethod KEYWORD1
NeoNrf52xPwm2Sk6812InvertedMethod KEYWORD1
NeoNrf52xPwm2Tm1814InvertedMethod KEYWORD1
NeoNrf52xPwm2800KbpsInvertedMethod KEYWORD1
NeoNrf52xPwm2400KbpsInvertedMethod KEYWORD1
NeoNrf52xPwm2Apa106InvertedMethod KEYWORD1
NeoNrf52xPwm3Ws2812xInvertedMethod KEYWORD1
NeoNrf52xPwm3Sk6812InvertedMethod KEYWORD1
NeoNrf52xPwm3Tm1814InvertedMethod KEYWORD1
NeoNrf52xPwm3800KbpsInvertedMethod KEYWORD1
NeoNrf52xPwm3400KbpsInvertedMethod KEYWORD1
NeoNrf52xPwm3Apa106InvertedMethod KEYWORD1
DotStarMethod KEYWORD1
DotStarSpiMethod KEYWORD1
DotStarSpi20MhzMethod KEYWORD1
DotStarSpi10MhzMethod KEYWORD1
DotStarSpi2MhzMethod KEYWORD1
NeoWs2801Method KEYWORD1
NeoWs2801SpiMethod KEYWORD1
NeoWs2801Spi20MhzMethod KEYWORD1
NeoWs2801Spi10MhzMethod KEYWORD1
NeoWs2801Spi2MhzMethod KEYWORD1
Lpd8806Method KEYWORD1
Lpd8806SpiMethod KEYWORD1
Lpd8806Spi20MhzMethod KEYWORD1
Lpd8806Spi10MhzMethod KEYWORD1
Lpd8806Spi2MhzMethod KEYWORD1
P9813Method KEYWORD1
P9813SpiMethod KEYWORD1
P9813Spi20MhzMethod KEYWORD1
P9813Spi10MhzMethod KEYWORD1
P9813Spi2MhzMethod KEYWORD1
NeoPixelAnimator KEYWORD1
AnimUpdateCallback KEYWORD1
AnimationParam KEYWORD1
NeoEase KEYWORD1
AnimEaseFunction KEYWORD1
RowMajorLayout KEYWORD1
RowMajor90Layout KEYWORD1
RowMajor180Layout KEYWORD1
RowMajor270Layout KEYWORD1
RowMajorAlternatingLayout KEYWORD1
RowMajorAlternating90Layout KEYWORD1
RowMajorAlternating180Layout KEYWORD1
RowMajorAlternating270Layout KEYWORD1
ColumnMajorLayout KEYWORD1
ColumnMajor90Layout KEYWORD1
ColumnMajor180Layout KEYWORD1
ColumnMajor270Layout KEYWORD1
ColumnMajorAlternatingLayout KEYWORD1
ColumnMajorAlternating90Layout KEYWORD1
ColumnMajorAlternating180Layout KEYWORD1
ColumnMajorAlternating270Layout KEYWORD1
NeoTopology KEYWORD1
NeoRingTopology KEYWORD1
NeoTiles KEYWORD1
NeoMosaic KEYWORD1
NeoGammaEquationMethod KEYWORD1
NeoGammaTableMethod KEYWORD1
NeoGamma KEYWORD1
NeoHueBlendShortestDistance KEYWORD1
NeoHueBlendLongestDistance KEYWORD1
NeoHueBlendClockwiseDirection KEYWORD1
NeoHueBlendCounterClockwiseDirection KEYWORD1
NeoBufferContext KEYWORD1
LayoutMapCallback KEYWORD1
NeoBufferMethod KEYWORD1
NeoBufferProgmemMethod KEYWORD1
NeoBuffer KEYWORD1
NeoVerticalSpriteSheet KEYWORD1
NeoBitmapFile KEYWORD1
HtmlShortColorNames KEYWORD1
HtmlColorNames KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
Begin KEYWORD2
Show KEYWORD2
CanShow KEYWORD2
ClearTo KEYWORD2
RotateLeft KEYWORD2
ShiftLeft KEYWORD2
RotateRight KEYWORD2
ShiftRight KEYWORD2
IsDirty KEYWORD2
Dirty KEYWORD2
ResetDirty KEYWORD2
Pixels KEYWORD2
PixelSize KEYWORD2
PixelsSize KEYWORD2
PixelCount KEYWORD2
SetPixelColor KEYWORD2
GetPixelColor KEYWORD2
SwapPixelColor KEYWORD2
CalculateBrightness KEYWORD2
Dim KEYWORD2
Brighten KEYWORD2
Darken KEYWORD2
Lighten KEYWORD2
SetPixelSettings KEYWORD2
LinearBlend KEYWORD2
BilinearBlend KEYWORD2
IsAnimating KEYWORD2
NextAvailableAnimation KEYWORD2
StartAnimation KEYWORD2
StopAnimation KEYWORD2
RestartAnimation KEYWORD2
IsAnimationActive KEYWORD2
AnimationDuration KEYWORD2
ChangeAnimationDuration KEYWORD2
UpdateAnimations KEYWORD2
IsPaused KEYWORD2
Pause KEYWORD2
Resume KEYWORD2
getTimeScale KEYWORD2
setTimeScale KEYWORD2
QuadraticIn KEYWORD2
QuadraticOut KEYWORD2
QuadraticInOut KEYWORD2
QuadraticCenter KEYWORD2
CubicIn KEYWORD2
CubicOut KEYWORD2
CubicInOut KEYWORD2
CubicCenter KEYWORD2
QuarticIn KEYWORD2
QuarticOut KEYWORD2
QuarticInOut KEYWORD2
QuarticCenter KEYWORD2
QuinticIn KEYWORD2
QuinticOut KEYWORD2
QuinticInOut KEYWORD2
QuinticCenter KEYWORD2
SinusoidalIn KEYWORD2
SinusoidalOut KEYWORD2
SinusoidalInOut KEYWORD2
SinusoidalCenter KEYWORD2
ExponentialIn KEYWORD2
ExponentialOut KEYWORD2
ExponentialInOut KEYWORD2
ExponentialCenter KEYWORD2
CircularIn KEYWORD2
CircularOut KEYWORD2
CircularInOut KEYWORD2
CircularCenter KEYWORD2
Gamma KEYWORD2
Map KEYWORD2
MapProbe KEYWORD2
getWidth KEYWORD2
getHeight KEYWORD2
RingPixelShift KEYWORD2
RingPixelRotate KEYWORD2
getCountOfRings KEYWORD2
getPixelCountAtRing KEYWORD2
getPixelCount KEYWORD2
TopologyHint KEYWORD2
Correct KEYWORD2
SpriteWidth KEYWORD2
SpriteHeight KEYWORD2
SpriteCount KEYWORD2
Blt KEYWORD2
Width KEYWORD2
Height KEYWORD2
Parse KEYWORD2
ToString KEYWORD2
ToNumericalString KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
NEO_MILLISECONDS LITERAL1
NEO_CENTISECONDS LITERAL1
NEO_DECISECONDS LITERAL1
NEO_SECONDS LITERAL1
NEO_DECASECONDS LITERAL1
AnimationState_Started LITERAL1
AnimationState_Progress LITERAL1
AnimationState_Completed LITERAL1
NeoTopologyHint_FirstOnPanel LITERAL1
NeoTopologyHint_InPanel LITERAL1
NeoTopologyHint_LastOnPanel LITERAL1
NeoTopologyHint_OutOfBounds LITERAL1
PixelIndex_OutOfBounds LITERAL1

View File

@ -0,0 +1,14 @@
{
"name": "NeoPixelBus",
"keywords": "NeoPixel, WS2811, WS2812, WS2813, SK6812, DotStar, APA102, SK9822, APA106, LPD8806, P9813, WS2801 RGB, RGBW",
"description": "A library that makes controlling NeoPixels (APA106, WS2811, WS2812, WS2813 & SK6812) and DotStars (APA102, LPD8806, SK9822, WS2801, P9813) easy. Supports most Arduino platforms, including async hardware support for Esp8266, Esp32, and Nrf52 (Nano 33 BLE). Support for RGBW pixels. Includes seperate RgbColor, RgbwColor, HslColor, and HsbColor objects. Includes an animator class that helps create asyncronous animations. For Esp8266 it has three methods of sending NeoPixel data, DMA, UART, and Bit Bang. For Esp32 it has two base methods of sending NeoPixel data, i2s and RMT. For all platforms, there are two methods of sending DotStar data, hardware SPI and software SPI.",
"homepage": "https://github.com/Makuna/NeoPixelBus/wiki",
"repository": {
"type": "git",
"url": "https://github.com/Makuna/NeoPixelBus"
},
"version": "2.6.0",
"frameworks": "arduino",
"platforms": "*"
}

View File

@ -0,0 +1,9 @@
name=NeoPixelBus by Makuna
version=2.6.0
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.
paragraph=Supports most Arduino platforms, including async hardware support for Esp8266, Esp32, and Nrf52 (Nano 33 BLE). Support for RGBW pixels. Includes seperate RgbColor, RgbwColor, HslColor, and HsbColor objects. Includes an animator class that helps create asyncronous animations. Supports Matrix layout of pixels. Includes Gamma corretion object. For Esp8266 it has three methods of sending NeoPixel data, DMA, UART, and Bit Bang. For Esp32 it has two base methods of sending NeoPixel data, i2s and RMT. For all platforms, there are two methods of sending DotStar data, hardware SPI and software SPI.
category=Display
url=https://github.com/Makuna/NeoPixelBus/wiki
architectures=*

View File

@ -43,7 +43,7 @@ struct AnimationParam
AnimationState state;
};
#ifdef ARDUINO_ARCH_AVR
#if defined(NEOPIXEBUS_NO_STL)
typedef void(*AnimUpdateCallback)(const AnimationParam& param);
@ -153,7 +153,6 @@ private:
_duration = duration;
_remaining = duration;
_fnCallback = animUpdate;
}
void StopAnimation()

View File

@ -32,100 +32,81 @@ template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelBrightnessBu
public NeoPixelBus<T_COLOR_FEATURE, T_METHOD>
{
private:
void ScaleColor(uint16_t scale, typename T_COLOR_FEATURE::ColorObject* color)
{
uint8_t* ptr = (uint8_t*)color;
uint8_t* ptrEnd = ptr + sizeof(typename T_COLOR_FEATURE::ColorObject);
while (ptr != ptrEnd)
{
uint16_t value = *ptr;
*ptr++ = (value * scale) >> 8;
}
}
void ConvertColor(typename T_COLOR_FEATURE::ColorObject* color)
{
if (_brightness)
{
uint8_t* ptr = (uint8_t*) color;
uint8_t* ptrEnd = ptr + T_COLOR_FEATURE::PixelSize;
while (ptr != ptrEnd)
{
uint16_t value = *ptr;
*ptr++ = (value * _brightness) >> 8;
}
}
uint16_t scale = _brightness + 1;
ScaleColor(scale, color);
}
void RecoverColor(typename T_COLOR_FEATURE::ColorObject* color) const
{
if (_brightness)
{
uint8_t* ptr = (uint8_t*) color;
uint8_t* ptrEnd = ptr + T_COLOR_FEATURE::PixelSize;
uint8_t* ptr = (uint8_t*)color;
uint8_t* ptrEnd = ptr + sizeof(typename T_COLOR_FEATURE::ColorObject);
uint16_t scale = _brightness + 1;
while (ptr != ptrEnd)
{
uint16_t value = *ptr;
*ptr++ = (value << 8) / _brightness;
}
while (ptr != ptrEnd)
{
uint16_t value = *ptr;
*ptr++ = (value << 8) / scale;
}
}
public:
NeoPixelBrightnessBus(uint16_t countPixels, uint8_t pin) :
NeoPixelBus<T_COLOR_FEATURE, T_METHOD>(countPixels, pin),
_brightness(0)
_brightness(255)
{
}
NeoPixelBrightnessBus(uint16_t countPixels, uint8_t pinClock, uint8_t pinData) :
NeoPixelBus<T_COLOR_FEATURE, T_METHOD>(countPixels, pinClock, pinData),
_brightness(0)
_brightness(255)
{
}
NeoPixelBrightnessBus(uint16_t countPixels) :
NeoPixelBus<T_COLOR_FEATURE, T_METHOD>(countPixels),
_brightness(0)
_brightness(255)
{
}
void SetBrightness(uint8_t brightness)
{
// Due to using fixed point math, we modifiy the brightness
// before storing making the math faster
uint8_t newBrightness = brightness + 1;
// Only update if there is a change
if (newBrightness != _brightness)
if (brightness != _brightness)
{
// calculate a scale to modify from old brightness to new brightness
uint16_t scale = (((uint16_t)brightness + 1) << 8) / ((uint16_t)_brightness + 1);
// scale existing pixels
//
uint8_t oldBrightness = _brightness - 1; // unmodify brightness value
uint16_t scale;
if (oldBrightness == 0)
for (uint16_t indexPixel = 0; indexPixel < NeoPixelBus<T_COLOR_FEATURE, T_METHOD>::PixelCount(); indexPixel++)
{
scale = 0; // Avoid divide by 0
typename T_COLOR_FEATURE::ColorObject color = NeoPixelBus<T_COLOR_FEATURE, T_METHOD>::GetPixelColor(indexPixel);
ScaleColor(scale, &color);
NeoPixelBus<T_COLOR_FEATURE, T_METHOD>::SetPixelColor(indexPixel, color);
}
else if (brightness == 255)
{
scale = 65535 / oldBrightness;
}
else
{
scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
}
// re-scale existing pixels
//
uint8_t* ptr = this->Pixels();
uint8_t* ptrEnd = ptr + this->PixelsSize();
while (ptr != ptrEnd)
{
uint16_t value = *ptr;
*ptr++ = (value * scale) >> 8;
}
_brightness = newBrightness;
_brightness = brightness;
this->Dirty();
}
}
uint8_t GetBrightness() const
{
return _brightness - 1;
return _brightness;
}
void SetPixelColor(uint16_t indexPixel, typename T_COLOR_FEATURE::ColorObject color)

View File

@ -27,6 +27,16 @@ License along with NeoPixel. If not, see
#include <Arduino.h>
// some platforms do not come with STL or properly defined one, specifically functional
// if you see...
// undefined reference to `std::__throw_bad_function_call()'
// ...then you can either add the platform symbol to the list so NEOPIXEBUS_NO_STL gets defined or
// go to boards.txt and enable c++ by adding (teensy31.build.flags.libs=-lstdc++) and set to "smallest code" option in Arduino
//
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) || defined(STM32L432xx) || defined(STM32L476xx) || defined(ARDUINO_ARCH_SAM)
#define NEOPIXEBUS_NO_STL 1
#endif
// some platforms do not define this standard progmem type for some reason
//
#ifndef PGM_VOID_P
@ -38,14 +48,21 @@ License along with NeoPixel. If not, see
#include "internal/NeoHueBlend.h"
#include "internal/NeoSettings.h"
#include "internal/RgbColor.h"
#include "internal/HslColor.h"
#include "internal/HsbColor.h"
#include "internal/HtmlColor.h"
#include "internal/RgbwColor.h"
#include "internal/SegmentDigit.h"
#include "internal/NeoColorFeatures.h"
#include "internal/NeoTm1814ColorFeatures.h"
#include "internal/DotStarColorFeatures.h"
#include "internal/Lpd8806ColorFeatures.h"
#include "internal/P9813ColorFeatures.h"
#include "internal/NeoSegmentFeatures.h"
#include "internal/Layouts.h"
#include "internal/NeoTopology.h"
@ -63,37 +80,40 @@ License along with NeoPixel. If not, see
#include "internal/NeoEase.h"
#include "internal/NeoGamma.h"
#include "internal/DotStarGenericMethod.h"
#include "internal/Lpd8806GenericMethod.h"
#include "internal/Ws2801GenericMethod.h"
#include "internal/P9813GenericMethod.h"
#if defined(ARDUINO_ARCH_ESP8266)
#include "internal/NeoEsp8266DmaMethod.h"
#include "internal/NeoEsp8266UartMethod.h"
#include "internal/NeoEspBitBangMethod.h"
#include "internal/DotStarGenericMethod.h"
#elif defined(ARDUINO_ARCH_ESP32)
#include "internal/NeoEsp32I2sMethod.h"
#include "internal/NeoEsp32RmtMethod.h"
#include "internal/NeoEspBitBangMethod.h"
#include "internal/DotStarGenericMethod.h"
#elif defined(ARDUINO_ARCH_NRF52840) // must be before __arm__
#include "internal/NeoNrf52xMethod.h"
#elif defined(__arm__) // must be before ARDUINO_ARCH_AVR due to Teensy incorrectly having it set
#include "internal/NeoArmMethod.h"
#include "internal/DotStarGenericMethod.h"
#elif defined(ARDUINO_ARCH_AVR)
#elif defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
#include "internal/NeoAvrMethod.h"
#include "internal/DotStarAvrMethod.h"
#else
#error "Platform Currently Not Supported, please add an Issue at Github/Makuna/NeoPixelBus"
#endif
#if !defined(__AVR_ATtiny85__)
#include "internal/DotStarSpiMethod.h"
#endif
template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelBus
@ -105,21 +125,21 @@ public:
NeoPixelBus(uint16_t countPixels, uint8_t pin) :
_countPixels(countPixels),
_state(0),
_method(pin, countPixels, T_COLOR_FEATURE::PixelSize)
_method(pin, countPixels, T_COLOR_FEATURE::PixelSize, T_COLOR_FEATURE::SettingsSize)
{
}
NeoPixelBus(uint16_t countPixels, uint8_t pinClock, uint8_t pinData) :
_countPixels(countPixels),
_state(0),
_method(pinClock, pinData, countPixels, T_COLOR_FEATURE::PixelSize)
_method(pinClock, pinData, countPixels, T_COLOR_FEATURE::PixelSize, T_COLOR_FEATURE::SettingsSize)
{
}
NeoPixelBus(uint16_t countPixels) :
_countPixels(countPixels),
_state(0),
_method(countPixels, T_COLOR_FEATURE::PixelSize)
_method(countPixels, T_COLOR_FEATURE::PixelSize, T_COLOR_FEATURE::SettingsSize)
{
}
@ -130,7 +150,7 @@ public:
operator NeoBufferContext<T_COLOR_FEATURE>()
{
Dirty(); // we assume you are playing with bits
return NeoBufferContext<T_COLOR_FEATURE>(_method.getPixels(), _method.getPixelsSize());
return NeoBufferContext<T_COLOR_FEATURE>(_pixels(), PixelsSize());
}
void Begin()
@ -180,12 +200,12 @@ public:
uint8_t* Pixels()
{
return _method.getPixels();
return _pixels();
};
size_t PixelsSize() const
{
return _method.getPixelsSize();
return _method.getDataSize() - T_COLOR_FEATURE::SettingsSize;
};
size_t PixelSize() const
@ -202,7 +222,7 @@ public:
{
if (indexPixel < _countPixels)
{
T_COLOR_FEATURE::applyPixelColor(_method.getPixels(), indexPixel, color);
T_COLOR_FEATURE::applyPixelColor(_pixels(), indexPixel, color);
Dirty();
}
};
@ -211,7 +231,7 @@ public:
{
if (indexPixel < _countPixels)
{
return T_COLOR_FEATURE::retrievePixelColor(_method.getPixels(), indexPixel);
return T_COLOR_FEATURE::retrievePixelColor(_pixels(), indexPixel);
}
else
{
@ -224,7 +244,7 @@ public:
void ClearTo(typename T_COLOR_FEATURE::ColorObject color)
{
uint8_t temp[T_COLOR_FEATURE::PixelSize];
uint8_t* pixels = _method.getPixels();
uint8_t* pixels = _pixels();
T_COLOR_FEATURE::applyPixelColor(temp, 0, color);
@ -240,7 +260,7 @@ public:
first <= last)
{
uint8_t temp[T_COLOR_FEATURE::PixelSize];
uint8_t* pixels = _method.getPixels();
uint8_t* pixels = _pixels();
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first);
T_COLOR_FEATURE::applyPixelColor(temp, 0, color);
@ -339,18 +359,49 @@ public:
SetPixelColor(indexPixelOne, colorTwo);
SetPixelColor(indexPixelTwo, colorOne);
};
void SetPixelSettings(const typename T_COLOR_FEATURE::SettingsObject& settings)
{
T_COLOR_FEATURE::applySettings(_method.getData(), settings);
Dirty();
};
uint32_t CalcTotalMilliAmpere(const typename T_COLOR_FEATURE::ColorObject::SettingsObject& settings)
{
uint32_t total = 0; // in 1/10th milliamps
for (uint16_t index = 0; index < _countPixels; index++)
{
auto color = GetPixelColor(index);
total += color.CalcTotalTenthMilliAmpere(settings);
}
return total / 10; // return millamps
}
protected:
const uint16_t _countPixels; // Number of RGB LEDs in strip
uint8_t _state; // internal state
T_METHOD _method;
uint8_t* _pixels()
{
// get pixels data within the data stream
return T_COLOR_FEATURE::pixels(_method.getData());
}
const uint8_t* _pixels() const
{
// get pixels data within the data stream
return T_COLOR_FEATURE::pixels(_method.getData());
}
void _rotateLeft(uint16_t rotationCount, uint16_t first, uint16_t last)
{
// store in temp
uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize];
uint8_t* pixels = _method.getPixels();
uint8_t* pixels = _pixels();
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first);
@ -371,7 +422,7 @@ protected:
uint16_t front = first + shiftCount;
uint16_t count = last - front + 1;
uint8_t* pixels = _method.getPixels();
uint8_t* pixels = _pixels();
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first);
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, front);
@ -384,7 +435,7 @@ protected:
{
// store in temp
uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize];
uint8_t* pixels = _method.getPixels();
uint8_t* pixels = _pixels();
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, last - (rotationCount - 1));
@ -405,7 +456,7 @@ protected:
uint16_t front = first + shiftCount;
uint16_t count = last - front + 1;
uint8_t* pixels = _method.getPixels();
uint8_t* pixels = _pixels();
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first);
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, front);

View File

@ -0,0 +1,67 @@
/*-------------------------------------------------------------------------
NeoPixelBus library wrapper template class that provides enhanced methods
for writing to segment based strips
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
#include "NeoPixelBus.h"
template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelSegmentBus :
public NeoPixelBus<T_COLOR_FEATURE, T_METHOD>
{
public:
NeoPixelSegmentBus(uint16_t countPixels, uint8_t pin) :
NeoPixelBus<T_COLOR_FEATURE, T_METHOD>(countPixels, pin)
{
}
NeoPixelSegmentBus(uint16_t countPixels) :
NeoPixelBus<T_COLOR_FEATURE, T_METHOD>(countPixels)
{
}
void SetString(uint16_t indexDigit,
const char* str,
uint8_t brightness,
uint8_t defaultBrightness = 0)
{
T_COLOR_FEATURE::ColorObject::SetString(*this,
indexDigit,
str,
brightness,
defaultBrightness);
}
void SetString(uint16_t indexDigit,
const String& str,
uint8_t brightness,
uint8_t defaultBrightness = 0)
{
SetString(indexDigit, str.c_str(), brightness, defaultBrightness);
}
};

View File

@ -160,7 +160,50 @@ public:
typedef RgbwColor ColorObject;
};
class DotStarBgrFeature : public DotStar3Elements
class DotStar3ElementsNoSettings : public DotStar3Elements
{
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 DotStar4ElementsNoSettings : public DotStar4Elements
{
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 DotStarBgrFeature : public DotStar3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -173,10 +216,10 @@ public:
*p = color.R;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
p++; // ignore the first byte
color.B = *p++;
@ -201,7 +244,7 @@ public:
};
class DotStarLbgrFeature : public DotStar4Elements
class DotStarLbgrFeature : public DotStar4ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -214,10 +257,10 @@ public:
*p = color.R;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.W = (*p++) & 0x1F; // mask out upper three bits
color.B = *p++;
@ -242,7 +285,7 @@ public:
};
class DotStarGrbFeature : public DotStar3Elements
class DotStarGrbFeature : public DotStar3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -255,10 +298,10 @@ public:
*p = color.B;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
p++; // ignore the first byte
color.G = *p++;
@ -283,7 +326,7 @@ public:
};
class DotStarLgrbFeature : public DotStar4Elements
class DotStarLgrbFeature : public DotStar4ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -296,10 +339,10 @@ public:
*p = color.B;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.W = (*p++) & 0x1F; // mask out upper three bits
color.G = *p++;
@ -325,7 +368,7 @@ public:
};
/* RGB Feature -- Some APA102s ship in RGB order */
class DotStarRgbFeature : public DotStar3Elements
class DotStarRgbFeature : public DotStar3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -338,10 +381,10 @@ public:
*p = color.B;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
p++; // ignore the first byte
color.R = *p++;
@ -366,7 +409,7 @@ public:
};
class DotStarLrgbFeature : public DotStar4Elements
class DotStarLrgbFeature : public DotStar4ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -379,10 +422,10 @@ public:
*p = color.B;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.W = (*p++) & 0x1F; // mask out upper three bits
color.R = *p++;
@ -407,7 +450,7 @@ public:
};
/* RBG Feature -- Some APA102s ship in RBG order */
class DotStarRbgFeature : public DotStar3Elements
class DotStarRbgFeature : public DotStar3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -420,10 +463,10 @@ public:
*p = color.G;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
p++; // ignore the first byte
color.R = *p++;
@ -448,7 +491,7 @@ public:
};
class DotStarLrbgFeature : public DotStar4Elements
class DotStarLrbgFeature : public DotStar4ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -461,10 +504,10 @@ public:
*p = color.G;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.W = (*p++) & 0x1F; // mask out upper three bits
color.R = *p++;
@ -490,7 +533,7 @@ public:
};
/* GBR Feature -- Some APA102s ship in GBR order */
class DotStarGbrFeature : public DotStar3Elements
class DotStarGbrFeature : public DotStar3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -503,10 +546,10 @@ public:
*p = color.R;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
p++; // ignore the first byte
color.G = *p++;
@ -531,7 +574,7 @@ public:
};
class DotStarLgbrFeature : public DotStar4Elements
class DotStarLgbrFeature : public DotStar4ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -544,10 +587,10 @@ public:
*p = color.R;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.W = (*p++) & 0x1F; // mask out upper three bits
color.G = *p++;
@ -572,7 +615,7 @@ public:
};
/* BRG Feature -- Some APA102s ship in BRG order */
class DotStarBrgFeature : public DotStar3Elements
class DotStarBrgFeature : public DotStar3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -585,10 +628,10 @@ public:
*p = color.G;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
p++; // ignore the first byte
color.B = *p++;
@ -613,7 +656,7 @@ public:
};
class DotStarLbrgFeature : public DotStar4Elements
class DotStarLbrgFeature : public DotStar4ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -626,10 +669,10 @@ public:
*p = color.G;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.W = (*p++) & 0x1F; // mask out upper three bits
color.B = *p++;

View File

@ -0,0 +1,135 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for DotStars using general Pins (APA102).
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 DotStarMethodBase
{
public:
DotStarMethodBase(uint8_t pinClock, uint8_t pinData, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize),
_sizeEndFrame((pixelCount + 15) / 16), // 16 = div 2 (bit for every two pixels) div 8 (bits to bytes)
_wire(pinClock, pinData)
{
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
}
#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
DotStarMethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
DotStarMethodBase(SCK, MOSI, pixelCount, elementSize, settingsSize)
{
}
#endif
~DotStarMethodBase()
{
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 };
const uint8_t resetFrame[4] = { 0x00 };
_wire.beginTransaction();
// start frame
_wire.transmitBytes(startFrame, sizeof(startFrame));
// data
_wire.transmitBytes(_data, _sizeData);
// reset frame
_wire.transmitBytes(resetFrame, sizeof(resetFrame));
// end frame
// one bit for every two pixels with no less than 1 byte
for (size_t endFrameByte = 0; endFrameByte < _sizeEndFrame; endFrameByte++)
{
_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 _sizeEndFrame;
T_TWOWIRE _wire;
uint8_t* _data; // Holds LED color values
};
typedef DotStarMethodBase<TwoWireBitBangImple> DotStarMethod;
#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
#include "TwoWireSpiImple.h"
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed40Mhz>> DotStarSpi40MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> DotStarSpi20MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> DotStarSpi10MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> DotStarSpi2MhzMethod;
typedef DotStarSpi10MhzMethod DotStarSpiMethod;
#endif

View File

@ -26,8 +26,13 @@
#include "freertos/semphr.h"
#include "freertos/queue.h"
#if ESP_IDF_VERSION_MAJOR>=4
#include "esp_intr_alloc.h"
#else
#include "esp_intr.h"
#include "rom/ets_sys.h"
#endif
#include "soc/gpio_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/io_mux_reg.h"
@ -41,7 +46,10 @@
#include "Esp32_i2s.h"
#include "esp32-hal.h"
#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
@ -87,16 +95,23 @@ typedef struct {
static uint8_t i2s_silence_buf[I2S_DMA_SILENCE_LEN];
static i2s_bus_t I2S[2] = {
#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}
};
#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}
};
#endif
void IRAM_ATTR i2sDmaISR(void* arg);
bool i2sInitDmaItems(uint8_t bus_num);
bool i2sInitDmaItems(uint8_t bus_num) {
if (bus_num > 1) {
if (bus_num >= I2S_NUM_MAX) {
return false;
}
if (I2S[bus_num].tx_queue) {// already set
@ -153,7 +168,7 @@ bool i2sInitDmaItems(uint8_t bus_num) {
}
void i2sSetSilenceBuf(uint8_t bus_num, uint8_t* data, size_t len) {
if (bus_num > 1 || !data || !len) {
if (bus_num >= I2S_NUM_MAX || !data || !len) {
return;
}
I2S[bus_num].silence_buf = data;
@ -161,38 +176,43 @@ void i2sSetSilenceBuf(uint8_t bus_num, uint8_t* data, size_t 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 > 1 || div_a > 63 || div_b > 63 || bck > 63) {
if (bus_num >= I2S_NUM_MAX || div_a > 63 || div_b > 63 || bck > 63) {
return ESP_FAIL;
}
i2s_dev_t* i2s = I2S[bus_num].bus;
i2s->clkm_conf.clka_en = 0;
i2s->clkm_conf.clkm_div_a = div_a;
i2s->clkm_conf.clkm_div_b = div_b;
i2s->clkm_conf.clkm_div_num = div_num;
i2s->sample_rate_conf.tx_bck_div_num = bck;
i2s->sample_rate_conf.rx_bck_div_num = bck;
i2s->sample_rate_conf.tx_bits_mod = bits;
i2s->sample_rate_conf.rx_bits_mod = bits;
typeof(i2s->clkm_conf) clkm_conf;
clkm_conf.val = 0;
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
clkm_conf.clka_en = 0;
#else
clkm_conf.clk_sel = 2;
#endif
clkm_conf.clkm_div_a = div_a;
clkm_conf.clkm_div_b = div_b;
clkm_conf.clkm_div_num = div_num;
i2s->clkm_conf.val = clkm_conf.val;
typeof(i2s->sample_rate_conf) sample_rate_conf;
sample_rate_conf.val = 0;
sample_rate_conf.tx_bck_div_num = bck;
sample_rate_conf.rx_bck_div_num = bck;
sample_rate_conf.tx_bits_mod = bits;
sample_rate_conf.rx_bits_mod = bits;
i2s->sample_rate_conf.val = sample_rate_conf.val;
return ESP_OK;
}
void i2sSetTxDataMode(uint8_t bus_num, i2s_tx_chan_mod_t chan_mod, i2s_tx_fifo_mod_t fifo_mod) {
if (bus_num > 1) {
return;
}
I2S[bus_num].bus->conf_chan.tx_chan_mod = chan_mod; // 0:dual channel; 1:right channel; 2:left channel; 3:left channel constant; 4:right channel constant; (channels flipped if tx_msb_right == 1)
I2S[bus_num].bus->fifo_conf.tx_fifo_mod = fifo_mod; // 0:16-bit dual channel; 1:16-bit single channel; 2:32-bit dual channel; 3:32-bit single channel data
}
void i2sSetDac(uint8_t bus_num, bool right, bool left) {
if (bus_num > 1) {
if (bus_num >= I2S_NUM_MAX) {
return;
}
if (!right && !left) {
dac_output_disable(1);
dac_output_disable(2);
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;
@ -201,7 +221,7 @@ void i2sSetDac(uint8_t bus_num, bool right, bool left) {
return;
}
i2sSetPins(bus_num, -1, -1, -1, -1);
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;
@ -209,75 +229,56 @@ void i2sSetDac(uint8_t bus_num, bool right, bool left) {
dac_i2s_enable();
if (right) {// DAC1, right channel, GPIO25
dac_output_enable(1);
dac_output_enable(DAC_CHANNEL_1);
}
if (left) { // DAC2, left channel, GPIO26
dac_output_enable(2);
dac_output_enable(DAC_CHANNEL_2);
}
}
void i2sSetPins(uint8_t bus_num, int8_t out, int8_t ws, int8_t bck, int8_t in) {
if (bus_num > 1) {
void i2sSetPins(uint8_t bus_num, int8_t out, bool invert) {
if (bus_num >= I2S_NUM_MAX) {
return;
}
if ((ws >= 0 && I2S[bus_num].ws == -1) || (bck >= 0 && I2S[bus_num].bck == -1) || (out >= 0 && I2S[bus_num].out == -1)) {
i2sSetDac(bus_num, false, false);
}
if (ws >= 0) {
if (I2S[bus_num].ws != ws) {
if (I2S[bus_num].ws >= 0) {
gpio_matrix_out(I2S[bus_num].ws, 0x100, false, false);
}
I2S[bus_num].ws = ws;
pinMode(ws, OUTPUT);
gpio_matrix_out(ws, bus_num?I2S1O_WS_OUT_IDX:I2S0O_WS_OUT_IDX, false, false);
}
} else if (I2S[bus_num].ws >= 0) {
gpio_matrix_out(I2S[bus_num].ws, 0x100, false, false);
I2S[bus_num].ws = -1;
}
if (bck >= 0) {
if (I2S[bus_num].bck != bck) {
if (I2S[bus_num].bck >= 0) {
gpio_matrix_out(I2S[bus_num].bck, 0x100, false, false);
}
I2S[bus_num].bck = bck;
pinMode(bck, OUTPUT);
gpio_matrix_out(bck, bus_num?I2S1O_BCK_OUT_IDX:I2S0O_BCK_OUT_IDX, false, false);
}
} else if (I2S[bus_num].bck >= 0) {
gpio_matrix_out(I2S[bus_num].bck, 0x100, false, false);
I2S[bus_num].bck = -1;
}
if (out >= 0) {
if (I2S[bus_num].out != out) {
if (I2S[bus_num].out >= 0) {
gpio_matrix_out(I2S[bus_num].out, 0x100, false, false);
gpio_matrix_out(I2S[bus_num].out, 0x100, invert, false);
}
I2S[bus_num].out = out;
pinMode(out, OUTPUT);
gpio_matrix_out(out, bus_num?I2S1O_DATA_OUT23_IDX:I2S0O_DATA_OUT23_IDX, false, false);
int i2sSignal;
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
// (I2S_NUM_MAX == 2)
if (bus_num == 1) {
i2sSignal = I2S1O_DATA_OUT23_IDX;
}
else
#endif
{
i2sSignal = I2S0O_DATA_OUT23_IDX;
}
gpio_matrix_out(out, i2sSignal, invert, false);
}
} else if (I2S[bus_num].out >= 0) {
gpio_matrix_out(I2S[bus_num].out, 0x100, false, false);
gpio_matrix_out(I2S[bus_num].out, 0x100, invert, false);
I2S[bus_num].out = -1;
}
}
bool i2sWriteDone(uint8_t bus_num) {
if (bus_num > 1) {
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);
}
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 > 1) {
if (bus_num >= I2S_NUM_MAX) {
return;
}
@ -288,9 +289,13 @@ void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2
return;
}
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
// (I2S_NUM_MAX == 2)
if (bus_num) {
periph_module_enable(PERIPH_I2S1_MODULE);
} else {
} else
#endif
{
periph_module_enable(PERIPH_I2S0_MODULE);
}
@ -321,42 +326,37 @@ void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2
i2s->lc_conf.out_rst = 0;
// Enable and configure DMA
i2s->lc_conf.check_owner = 0;
i2s->lc_conf.out_loop_test = 0;
i2s->lc_conf.out_auto_wrback = 0;
i2s->lc_conf.out_data_burst_en = 0;
i2s->lc_conf.outdscr_burst_en = 0;
i2s->lc_conf.out_no_restart_clr = 0;
i2s->lc_conf.indscr_burst_en = 0;
i2s->lc_conf.out_eof_mode = 1;
typeof(i2s->lc_conf) lc_conf;
lc_conf.val = 0;
lc_conf.out_eof_mode = 1;
i2s->lc_conf.val = lc_conf.val;
i2s->pdm_conf.pcm2pdm_conv_en = 0;
i2s->pdm_conf.pdm2pcm_conv_en = 0;
// 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;
conf_chan.val = 0;
conf_chan.tx_chan_mod = chan_mod; // 0-two channel;1-right;2-left;3-righ;4-left
conf_chan.rx_chan_mod = chan_mod; // 0-two channel;1-right;2-left;3-righ;4-left
i2s->conf_chan.val = conf_chan.val;
i2s->conf_chan.tx_chan_mod = chan_mod; // 0-two channel;1-right;2-left;3-righ;4-left
i2s->conf_chan.rx_chan_mod = chan_mod; // 0-two channel;1-right;2-left;3-righ;4-left
i2s->fifo_conf.tx_fifo_mod = fifo_mod; // 0-right&left channel;1-one channel
i2s->fifo_conf.rx_fifo_mod = fifo_mod; // 0-right&left channel;1-one channel
typeof(i2s->fifo_conf) fifo_conf;
fifo_conf.val = 0;
fifo_conf.tx_fifo_mod = fifo_mod; // 0-right&left channel;1-one channel
fifo_conf.rx_fifo_mod = fifo_mod; // 0-right&left channel;1-one channel
i2s->fifo_conf.val = fifo_conf.val;
i2s->conf.tx_mono = 0;
i2s->conf.rx_mono = 0;
typeof(i2s->conf) conf;
conf.val = 0;
conf.tx_msb_shift = (bits_per_sample != 8);// 0:DAC/PCM, 1:I2S
conf.tx_right_first = (bits_per_sample == 8);
i2s->conf.val = conf.val;
i2s->conf.tx_start = 0;
i2s->conf.rx_start = 0;
i2s->conf.tx_short_sync = 0;
i2s->conf.rx_short_sync = 0;
i2s->conf.tx_msb_shift = (bits_per_sample != 8);// 0:DAC/PCM, 1:I2S
i2s->conf.rx_msb_shift = 0;
i2s->conf.tx_slave_mod = 0; // Master
i2s->conf.tx_msb_right = 0;
i2s->conf.tx_right_first = (bits_per_sample == 8);
i2s->conf2.lcd_en = (bits_per_sample == 8);
i2s->conf2.camera_en = 0;
typeof(i2s->conf2) conf2;
conf2.val = 0;
conf2.lcd_en = (bits_per_sample == 8);
i2s->conf2.val = conf2.val;
i2s->fifo_conf.tx_fifo_mod_force_en = 1;
@ -366,7 +366,21 @@ void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2
i2sSetSampleRate(bus_num, sample_rate, bits_per_sample);
// enable intr in cpu //
esp_intr_alloc(bus_num?ETS_I2S1_INTR_SOURCE:ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1, &i2sDmaISR, &I2S[bus_num], &I2S[bus_num].isr_handle);
int i2sIntSource;
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
// (I2S_NUM_MAX == 2)
if (bus_num == 1) {
i2sIntSource = ETS_I2S1_INTR_SOURCE;
}
else
#endif
{
i2sIntSource = ETS_I2S0_INTR_SOURCE;
}
esp_intr_alloc(i2sIntSource, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1, &i2sDmaISR, &I2S[bus_num], &I2S[bus_num].isr_handle);
// enable send intr
i2s->int_ena.out_eof = 1;
i2s->int_ena.out_dscr_err = 1;
@ -381,7 +395,7 @@ void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2
}
esp_err_t i2sSetSampleRate(uint8_t bus_num, uint32_t rate, uint8_t bits) {
if (bus_num > 1) {
if (bus_num >= I2S_NUM_MAX) {
return ESP_FAIL;
}
@ -451,7 +465,7 @@ void IRAM_ATTR i2sDmaISR(void* arg)
}
size_t i2sWrite(uint8_t bus_num, uint8_t* data, size_t len, bool copy, bool free_when_sent) {
if (bus_num > 1 || !I2S[bus_num].tx_queue) {
if (bus_num >= I2S_NUM_MAX || !I2S[bus_num].tx_queue) {
return 0;
}
size_t index = 0;

View File

@ -20,14 +20,12 @@ typedef enum {
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, int8_t ws, int8_t bck, int8_t in);
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 i2sSetTxDataMode(uint8_t bus_num, i2s_tx_chan_mod_t chan_mod, i2s_tx_fifo_mod_t fifo_mod);
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);

View File

@ -0,0 +1,189 @@
/*-------------------------------------------------------------------------
Lpd8806ColorFeatures 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 Lpd88063ElementsNoSettings
{
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 Lpd88063Elements : public Lpd88063ElementsNoSettings
{
public:
static const size_t PixelSize = 3;
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];
*pPixelDest++ = pPixelSrc[2];
}
}
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++;
*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++);
*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;
*--pDestBack = *--pSrcBack;
}
}
typedef RgbColor ColorObject;
};
class Lpd8806BrgFeature : public Lpd88063Elements
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
{
uint8_t* p = getPixelAddress(pPixels, indexPixel);
*p++ = (color.B >> 1) | 0x80;
*p++ = (color.R >> 1) | 0x80;
*p = (color.G >> 1) | 0x80;
}
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.B = (*p++) << 1;
color.R = (*p++) << 1;
color.G = (*p) << 1;
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);
color.B = (pgm_read_byte(p++)) << 1;
color.R = (pgm_read_byte(p++)) << 1;
color.G = (pgm_read_byte(p)) << 1;
return color;
}
};
class Lpd8806GrbFeature : public Lpd88063Elements
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
{
uint8_t* p = getPixelAddress(pPixels, indexPixel);
*p++ = (color.G >> 1) | 0x80;
*p++ = (color.R >> 1) | 0x80;
*p = (color.B >> 1) | 0x80;
}
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.G = (*p++) << 1;
color.R = (*p++) << 1;
color.B = (*p) << 1;
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);
color.G = (pgm_read_byte(p++)) << 1;
color.R = (pgm_read_byte(p++)) << 1;
color.B = (pgm_read_byte(p)) << 1;
return color;
}
};

View File

@ -0,0 +1,130 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for LPD8806 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 Lpd8806MethodBase
{
public:
Lpd8806MethodBase(uint8_t pinClock, uint8_t pinData, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize),
_sizeFrame((pixelCount + 31) / 32),
_wire(pinClock, pinData)
{
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
}
#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
Lpd8806MethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
Lpd8806MethodBase(SCK, MOSI, pixelCount, elementSize, settingsSize)
{
}
#endif
~Lpd8806MethodBase()
{
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)
{
_wire.beginTransaction();
// start frame
for (size_t frameByte = 0; frameByte < _sizeFrame; frameByte++)
{
_wire.transmitByte(0x00);
}
// data
_wire.transmitBytes(_data, _sizeData);
// end frame
for (size_t frameByte = 0; frameByte < _sizeFrame; frameByte++)
{
_wire.transmitByte(0xff);
}
_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 Lpd8806MethodBase<TwoWireBitBangImple> Lpd8806Method;
#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
#include "TwoWireSpiImple.h"
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> Lpd8806Spi20MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> Lpd8806Spi10MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> Lpd8806Spi2MhzMethod;
typedef Lpd8806Spi10MhzMethod Lpd8806SpiMethod;
#endif

View File

@ -30,26 +30,26 @@ License along with NeoPixel. If not, see
#pragma once
#if defined(__arm__)
#if defined(__arm__) && !defined(ARDUINO_ARCH_NRF52840)
template<typename T_SPEED> class NeoArmMethodBase
{
public:
NeoArmMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) :
NeoArmMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize),
_pin(pin)
{
pinMode(pin, OUTPUT);
_sizePixels = pixelCount * elementSize;
_pixels = (uint8_t*)malloc(_sizePixels);
memset(_pixels, 0, _sizePixels);
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
}
~NeoArmMethodBase()
{
pinMode(_pin, INPUT);
free(_pixels);
free(_data);
}
bool IsReadyToUpdate() const
@ -81,7 +81,7 @@ public:
noInterrupts(); // Need 100% focus on instruction timing
T_SPEED::send_pixels(_pixels, _sizePixels, _pin);
T_SPEED::send_pixels(_data, _sizeData, _pin);
interrupts();
@ -89,20 +89,21 @@ public:
_endTime = micros();
}
uint8_t* getPixels() const
uint8_t* getData() const
{
return _pixels;
return _data;
};
size_t getPixelsSize() const
size_t getDataSize() const
{
return _sizePixels;
return _sizeData;
};
private:
const size_t _sizeData; // Size of '_data' buffer below
uint32_t _endTime; // Latch timing reference
size_t _sizePixels; // Size of '_pixels' buffer below
uint8_t* _pixels; // Holds LED color values
uint8_t* _data; // Holds LED color values
uint8_t _pin; // output pin number
};
@ -129,6 +130,12 @@ public:
static const uint32_t ResetTimeUs = 80;
};
class NeoArmMk20dxSpeedPropsTm1814 : public NeoArmMk20dxSpeedProps800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 200;
};
class NeoArmMk20dxSpeedProps800Kbps : public NeoArmMk20dxSpeedProps800KbpsBase
{
public:
@ -147,10 +154,10 @@ public:
class NeoArmMk20dxSpeedPropsApa106
{
public:
static const uint32_t CyclesT0h = (F_CPU / 4000000);
static const uint32_t CyclesT1h = (F_CPU / 913750);
static const uint32_t Cycles = (F_CPU / 584800);
static const uint32_t ResetTimeUs = 50;
static const uint32_t CyclesT0h = (F_CPU / 4000000);
static const uint32_t CyclesT1h = (F_CPU / 913750);
static const uint32_t Cycles = (F_CPU / 584800);
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEEDPROPS> class NeoArmMk20dxSpeedBase
@ -199,6 +206,7 @@ public:
typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedPropsWs2812x>> NeoArmWs2812xMethod;
typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedPropsSk6812>> NeoArmSk6812Method;
typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedPropsTm1814>> NeoArmTm1814InvertedMethod;
typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedPropsApa106>> NeoArmApa106Method;
typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedProps800Kbps>> NeoArm800KbpsMethod;
typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedProps400Kbps>> NeoArm400KbpsMethod;
@ -310,6 +318,12 @@ public:
const static uint32_t ResetTimeUs = 80;
};
class NeoArmMk26z64SpeedTm1814 : public NeoArmMk26z64Speed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 200;
};
class NeoArmMk26z64Speed800Kbps : public NeoArmMk26z64Speed800KbpsBase
{
public:
@ -318,6 +332,7 @@ public:
typedef NeoArmMethodBase<NeoArmMk26z64SpeedWs2812x> NeoArmWs2812xMethod;
typedef NeoArmMethodBase<NeoArmMk26z64SpeedSk6812> NeoArmSk6812Method;
typedef NeoArmMethodBase<NeoArmMk26z64SpeedTm1814> NeoArmTm1814InvertedMethod;
typedef NeoArmMethodBase<NeoArmMk26z64Speed800Kbps> NeoArm800KbpsMethod;
typedef NeoArm800KbpsMethod NeoArmApa106Method
@ -365,6 +380,12 @@ public:
static const uint32_t ResetTimeUs = 80;
};
class NeoArmSamd21g18aSpeedPropsTm1814 : public NeoArmSamd21g18aSpeedProps800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 200;
};
class NeoArmSamd21g18aSpeedProps800Kbps : public NeoArmSamd21g18aSpeedProps800KbpsBase
{
public:
@ -453,9 +474,10 @@ public:
typedef NeoArmMethodBase<NeoArmSamd21g18aSpeedBase<NeoArmSamd21g18aSpeedPropsWs2812x>> NeoArmWs2812xMethod;
typedef NeoArmMethodBase<NeoArmSamd21g18aSpeedBase<NeoArmSamd21g18aSpeedPropsSk6812>> NeoArmSk6812Method;
typedef NeoArmMethodBase<NeoArmSamd21g18aSpeedBase<NeoArmSamd21g18aSpeedPropsTm1814>> NeoArmTm1814InvertedMethod;
typedef NeoArmMethodBase<NeoArmSamd21g18aSpeedBase<NeoArmSamd21g18aSpeedProps800Kbps>> NeoArm800KbpsMethod;
typedef NeoArmMethodBase<NeoArmSamd21g18aSpeedBase<NeoArmSamd21g18aSpeedProps400Kbps>> NeoArm400KbpsMethod;
typedef NeoArm400KbpsMethod NeoArmApa106Method
typedef NeoArm400KbpsMethod NeoArmApa106Method;
#elif defined(ARDUINO_STM32_FEATHER) || defined(ARDUINO_ARCH_STM32L4) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32F1)// FEATHER WICED (120MHz)
@ -523,6 +545,12 @@ public:
static const uint32_t ResetTimeUs = 80;
};
class NeoArmStm32SpeedPropsTm1814 : public NeoArmStm32SpeedProps800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 200;
};
class NeoArmStm32SpeedProps800Kbps : public NeoArmStm32SpeedProps800KbpsBase
{
public:
@ -563,32 +591,32 @@ public:
uint8_t bitMask = 0x80;
#if defined(ARDUINO_STM32_FEATHER)
uint32_t pinMask = BIT(PIN_MAP[pin].gpio_bit);
uint32_t pinMask = BIT(PIN_MAP[pin].gpio_bit);
volatile uint16_t* set = &(PIN_MAP[pin].gpio_device->regs->BSRRL);
volatile uint16_t* clr = &(PIN_MAP[pin].gpio_device->regs->BSRRH);
volatile uint16_t* set = &(PIN_MAP[pin].gpio_device->regs->BSRRL);
volatile uint16_t* clr = &(PIN_MAP[pin].gpio_device->regs->BSRRH);
#elif defined(ARDUINO_ARCH_STM32F4)
uint32_t pinMask = BIT(pin & 0x0f);
uint32_t pinMask = BIT(pin & 0x0f);
volatile uint16_t* set = &(PIN_MAP[pin].gpio_device->regs->BSRRL);
volatile uint16_t* clr = &(PIN_MAP[pin].gpio_device->regs->BSRRH);
volatile uint16_t* set = &(PIN_MAP[pin].gpio_device->regs->BSRRL);
volatile uint16_t* clr = &(PIN_MAP[pin].gpio_device->regs->BSRRH);
#elif defined(ARDUINO_ARCH_STM32F1)
uint32_t pinMask = BIT(PIN_MAP[pin].gpio_bit);
uint32_t pinMask = BIT(PIN_MAP[pin].gpio_bit);
volatile uint32_t* set = &(PIN_MAP[pin].gpio_device->regs->BRR);
volatile uint32_t* clr = &(PIN_MAP[pin].gpio_device->regs->BSRR);
volatile uint32_t* set = &(PIN_MAP[pin].gpio_device->regs->BRR);
volatile uint32_t* clr = &(PIN_MAP[pin].gpio_device->regs->BSRR);
#elif defined(ARDUINO_ARCH_STM32L4)
uint32_t pinMask = g_APinDescription[pin].bit;
uint32_t pinMask = g_APinDescription[pin].bit;
GPIO_TypeDef* GPIO = static_cast<GPIO_TypeDef*>(g_APinDescription[pin].GPIO);
GPIO_TypeDef* GPIO = static_cast<GPIO_TypeDef*>(g_APinDescription[pin].GPIO);
volatile uint32_t* set = &(GPIO->BRR);
volatile uint32_t* clr = &(GPIO->BSRR);
volatile uint32_t* set = &(GPIO->BRR);
volatile uint32_t* clr = &(GPIO->BSRR);
#endif
for (;;)
@ -634,6 +662,7 @@ public:
typedef NeoArmMethodBase<NeoArmStm32SpeedBase<NeoArmStm32SpeedPropsWs2812x>> NeoArmWs2812xMethod;
typedef NeoArmMethodBase<NeoArmStm32SpeedBase<NeoArmStm32SpeedPropsSk6812>> NeoArmSk6812Method;
typedef NeoArmMethodBase<NeoArmStm32SpeedBase<NeoArmStm32SpeedPropstm1814>> NeoArmTm1814InvertedMethod;
typedef NeoArmMethodBase<NeoArmStm32SpeedBase<NeoArmStm32SpeedProps800Kbps>> NeoArm800KbpsMethod;
typedef NeoArm800KbpsMethod NeoArmApa106Method;
@ -663,6 +692,12 @@ public:
static const uint32_t ResetTimeUs = 80;
};
class NeoArmOtherSpeedPropsTm1814 : public NeoArmOtherSpeedProps800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 200;
};
class NeoArmOtherSpeedProps800Kbps : public NeoArmOtherSpeedProps800KbpsBase
{
public:
@ -756,6 +791,7 @@ public:
typedef NeoArmMethodBase<NeoArmOtherSpeedBase<NeoArmOtherSpeedPropsWs2812x>> NeoArmWs2812xMethod;
typedef NeoArmMethodBase<NeoArmOtherSpeedBase<NeoArmOtherSpeedPropsSk6812>> NeoArmSk6812Method;
typedef NeoArmMethodBase<NeoArmOtherSpeedBase<NeoArmOtherSpeedPropsTm1814>> NeoArmTm1814InvertedMethod;
typedef NeoArmMethodBase<NeoArmOtherSpeedBase<NeoArmOtherSpeedProps800Kbps>> NeoArm800KbpsMethod;
typedef NeoArmMethodBase<NeoArmOtherSpeedBase<NeoArmOtherSpeedProps400Kbps>> NeoArm400KbpsMethod;
typedef NeoArm400KbpsMethod NeoArmApa106Method;
@ -766,6 +802,7 @@ typedef NeoArm400KbpsMethod NeoArmApa106Method;
// Arm doesn't have alternatives methods yet, so only one to make the default
typedef NeoArmWs2812xMethod NeoWs2813Method;
typedef NeoArmWs2812xMethod NeoWs2812xMethod;
typedef NeoArmWs2812xMethod NeoWs2811Method;
typedef NeoArmSk6812Method NeoSk6812Method;
typedef NeoArmSk6812Method NeoLc8812Method;
typedef NeoArm800KbpsMethod NeoWs2812Method;
@ -774,6 +811,8 @@ typedef NeoArmWs2812xMethod Neo800KbpsMethod;
#ifdef NeoArm400KbpsMethod // this is needed due to missing 400Kbps for some platforms
typedef NeoArm400KbpsMethod Neo400KbpsMethod;
#endif
// there is no invert methods for arm, but the norm for TM1814 is inverted, so
typedef NeoArmTm1814InvertedMethod NeoTm1814InvertedMethod;
#endif // defined(__arm__)

View File

@ -27,43 +27,43 @@ License along with NeoPixel. If not, see
#pragma once
#ifdef ARDUINO_ARCH_AVR
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
extern "C"
{
void send_pixels_8mhz_800_PortD(uint8_t* pixels, size_t sizePixels, uint8_t pinMask);
void send_pixels_8mhz_800_PortB(uint8_t* pixels, size_t sizePixels, uint8_t pinMask);
void send_pixels_8mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask);
void send_pixels_12mhz_800_PortD(uint8_t* pixels, size_t sizePixels, uint8_t pinMask);
void send_pixels_12mhz_800_PortB(uint8_t* pixels, size_t sizePixels, uint8_t pinMask);
void send_pixels_12mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask);
void send_pixels_16mhz_800(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask);
void send_pixels_16mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask);
void send_data_8mhz_800_PortD(uint8_t* data, size_t sizeData, uint8_t pinMask);
void send_data_8mhz_800_PortB(uint8_t* data, size_t sizeData, uint8_t pinMask);
void send_data_8mhz_400(uint8_t* data, size_t sizeData, volatile uint8_t* port, uint8_t pinMask);
void send_data_12mhz_800_PortD(uint8_t* data, size_t sizeData, uint8_t pinMask);
void send_data_12mhz_800_PortB(uint8_t* data, size_t sizeData, uint8_t pinMask);
void send_data_12mhz_400(uint8_t* data, size_t sizeData, volatile uint8_t* port, uint8_t pinMask);
void send_data_16mhz_800(uint8_t* data, size_t sizeData, volatile uint8_t* port, uint8_t pinMask);
void send_data_16mhz_400(uint8_t* data, size_t sizeData, volatile uint8_t* port, uint8_t pinMask);
}
class NeoAvrSpeed800KbpsBase
{
public:
static void send_pixels(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask)
static void send_data(uint8_t* data, size_t sizeData, volatile uint8_t* port, uint8_t pinMask)
{
#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL) // 8Mhz CPU
#ifdef PORTD // PORTD isn't present on ATtiny85, etc.
if (port == &PORTD)
send_pixels_8mhz_800_PortD(pixels, sizePixels, pinMask);
send_data_8mhz_800_PortD(data, sizeData, pinMask);
else if (port == &PORTB)
#endif // PORTD
send_pixels_8mhz_800_PortB(pixels, sizePixels, pinMask);
send_data_8mhz_800_PortB(data, sizeData, pinMask);
#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL) // 12Mhz CPU
#ifdef PORTD // PORTD
if (port == &PORTD)
send_pixels_12mhz_800_PortD(pixels, sizePixels, pinMask);
send_data_12mhz_800_PortD(data, sizeData, pinMask);
else if (port == &PORTB)
#endif // PORTD
send_pixels_12mhz_800_PortB(pixels, sizePixels, pinMask);
send_data_12mhz_800_PortB(data, sizeData, pinMask);
#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L) // 16Mhz CPU
send_pixels_16mhz_800(pixels, sizePixels, port, pinMask);
send_data_16mhz_800(data, sizeData, port, pinMask);
#else
#error "CPU SPEED NOT SUPPORTED"
#endif
@ -83,6 +83,12 @@ public:
static const uint32_t ResetTimeUs = 80;
};
class NeoAvrSpeedTm1814 : public NeoAvrSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 200;
};
class NeoAvrSpeed800Kbps: public NeoAvrSpeed800KbpsBase
{
public:
@ -92,16 +98,16 @@ public:
class NeoAvrSpeed400Kbps
{
public:
static void send_pixels(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask)
static void send_data(uint8_t* data, size_t sizeData, volatile uint8_t* port, uint8_t pinMask)
{
#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL) // 8Mhz CPU
send_pixels_8mhz_400(pixels, sizePixels, port, pinMask);
send_data_8mhz_400(data, sizeData, port, pinMask);
#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL) // 12Mhz CPU
send_pixels_12mhz_400(pixels, sizePixels, port, pinMask);
send_data_12mhz_400(data, sizeData, port, pinMask);
#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L) // 16Mhz CPU
send_pixels_16mhz_400(pixels, sizePixels, port, pinMask);
send_data_16mhz_400(data, sizeData, port, pinMask);
#else
#error "CPU SPEED NOT SUPPORTED"
#endif
@ -112,16 +118,16 @@ public:
template<typename T_SPEED> class NeoAvrMethodBase
{
public:
NeoAvrMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) :
NeoAvrMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize),
_pin(pin),
_port(NULL),
_pinMask(0)
{
pinMode(pin, OUTPUT);
_sizePixels = pixelCount * elementSize;
_pixels = (uint8_t*)malloc(_sizePixels);
memset(_pixels, 0, _sizePixels);
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
_port = portOutputRegister(digitalPinToPort(pin));
_pinMask = digitalPinToBitMask(pin);
@ -131,7 +137,7 @@ public:
{
pinMode(_pin, INPUT);
free(_pixels);
free(_data);
}
bool IsReadyToUpdate() const
@ -165,7 +171,7 @@ public:
noInterrupts(); // Need 100% focus on instruction timing
T_SPEED::send_pixels(_pixels, _sizePixels, _port, _pinMask);
T_SPEED::send_data(_data, _sizeData, _port, _pinMask);
interrupts();
@ -173,22 +179,23 @@ public:
_endTime = micros();
}
uint8_t* getPixels() const
uint8_t* getData() const
{
return _pixels;
return _data;
};
size_t getPixelsSize() const
size_t getDataSize() const
{
return _sizePixels;
return _sizeData;
};
private:
uint32_t _endTime; // Latch timing reference
size_t _sizePixels; // Size of '_pixels' buffer below
uint8_t* _pixels; // Holds LED color values
uint8_t _pin; // output pin number
const size_t _sizeData; // size of _data below
const uint8_t _pin; // output pin number
uint32_t _endTime; // Latch timing reference
uint8_t* _data; // Holds data stream which include LED color values and other settings as needed
volatile uint8_t* _port; // Output PORT register
uint8_t _pinMask; // Output PORT bitmask
};
@ -196,6 +203,7 @@ private:
typedef NeoAvrMethodBase<NeoAvrSpeedWs2812x> NeoAvrWs2812xMethod;
typedef NeoAvrMethodBase<NeoAvrSpeedSk6812> NeoAvrSk6812Method;
typedef NeoAvrMethodBase<NeoAvrSpeedTm1814> NeoAvrTm1814InvertedMethod;
typedef NeoAvrMethodBase<NeoAvrSpeed800Kbps> NeoAvr800KbpsMethod;
typedef NeoAvrMethodBase<NeoAvrSpeed400Kbps> NeoAvr400KbpsMethod;
@ -204,11 +212,13 @@ typedef NeoAvrMethodBase<NeoAvrSpeed400Kbps> NeoAvr400KbpsMethod;
typedef NeoAvrWs2812xMethod NeoWs2813Method;
typedef NeoAvrWs2812xMethod NeoWs2812xMethod;
typedef NeoAvr800KbpsMethod NeoWs2812Method;
typedef NeoAvrWs2812xMethod NeoWs2811Method;
typedef NeoAvrSk6812Method NeoSk6812Method;
typedef NeoAvrSk6812Method NeoLc8812Method;
typedef NeoAvr400KbpsMethod NeoApa106Method;
typedef NeoAvrWs2812xMethod Neo800KbpsMethod;
typedef NeoAvr400KbpsMethod Neo400KbpsMethod;
typedef NeoAvrTm1814InvertedMethod NeoTm1814InvertedMethod;
#endif

View File

@ -282,7 +282,7 @@ public:
int16_t hSrc,
LayoutMapCallback layoutMap)
{
NeoShaderNop<typename T_COLOR_FEATURE::ColorObject> shaderNop;
NeoShaderNop<typename T_COLOR_FEATURE::ColorObject> shaderNop;
Render<NeoShaderNop<typename T_COLOR_FEATURE::ColorObject>>(destBuffer,
shaderNop,

View File

@ -27,7 +27,7 @@ License along with NeoPixel. If not, see
#pragma once
#ifdef ARDUINO_ARCH_AVR
#if defined(NEOPIXEBUS_NO_STL)
typedef uint16_t(*LayoutMapCallback)(int16_t x, int16_t y);

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------
NeoPixelFeatures provides feature classes to describe color order and
NeoColorFeatures provides feature classes to describe color order and
color depth for NeoPixelBus template class
Written by Michael C. Miller.
@ -45,9 +45,10 @@ public:
uint8_t* pEnd = pPixelDest + (count * PixelSize);
while (pPixelDest < pEnd)
{
*pPixelDest++ = pPixelSrc[0];
*pPixelDest++ = pPixelSrc[1];
*pPixelDest++ = pPixelSrc[2];
for (uint8_t iElement = 0; iElement < PixelSize; iElement++)
{
*pPixelDest++ = pPixelSrc[iElement];
}
}
}
@ -57,8 +58,6 @@ public:
while (pPixelDest < pEnd)
{
*pPixelDest++ = *pPixelSrc++;
*pPixelDest++ = *pPixelSrc++;
*pPixelDest++ = *pPixelSrc++;
}
}
@ -69,8 +68,6 @@ public:
while (pPixelDest < pEnd)
{
*pPixelDest++ = pgm_read_byte(pSrc++);
*pPixelDest++ = pgm_read_byte(pSrc++);
*pPixelDest++ = pgm_read_byte(pSrc++);
}
}
@ -81,8 +78,6 @@ public:
while (pDestBack > pPixelDest)
{
*--pDestBack = *--pSrcBack;
*--pDestBack = *--pSrcBack;
*--pDestBack = *--pSrcBack;
}
}
@ -152,7 +147,50 @@ public:
typedef RgbwColor ColorObject;
};
class NeoGrbFeature : public Neo3Elements
class Neo3ElementsNoSettings : public Neo3Elements
{
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 Neo4ElementsNoSettings : public Neo4Elements
{
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 NeoGrbFeature : public Neo3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -164,10 +202,10 @@ public:
*p = color.B;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.G = *p++;
color.R = *p++;
@ -190,7 +228,7 @@ public:
};
class NeoGrbwFeature : public Neo4Elements
class NeoGrbwFeature : public Neo4ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -203,10 +241,10 @@ public:
*p = color.W;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.G = *p++;
color.R = *p++;
@ -232,7 +270,7 @@ public:
};
class NeoRgbwFeature : public Neo4Elements
class NeoRgbwFeature : public Neo4ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -245,10 +283,10 @@ public:
*p = color.W;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.R = *p++;
color.G = *p++;
@ -273,7 +311,7 @@ public:
};
class NeoRgbFeature : public Neo3Elements
class NeoRgbFeature : public Neo3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -285,10 +323,10 @@ public:
*p = color.B;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.R = *p++;
color.G = *p++;
@ -311,7 +349,7 @@ public:
};
class NeoBrgFeature : public Neo3Elements
class NeoBrgFeature : public Neo3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -323,10 +361,10 @@ public:
*p = color.G;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.B = *p++;
color.R = *p++;
@ -349,7 +387,7 @@ public:
};
class NeoRbgFeature : public Neo3Elements
class NeoRbgFeature : public Neo3ElementsNoSettings
{
public:
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
@ -361,10 +399,10 @@ public:
*p = color.G;
}
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
static ColorObject retrievePixelColor(const uint8_t* pPixels, uint16_t indexPixel)
{
ColorObject color;
uint8_t* p = getPixelAddress(pPixels, indexPixel);
const uint8_t* p = getPixelAddress(pPixels, indexPixel);
color.R = *p++;
color.B = *p++;

View File

@ -94,6 +94,25 @@ public:
free((uint8_t*)_pixels);
}
NeoDib& operator=(const NeoDib& other)
{
// check for self-assignment
if (&other == this)
{
return *this;
}
uint16_t copyCount = other.PixelCount() < PixelCount() ? other.PixelCount() : PixelCount();
for (uint16_t pixel = 0; pixel < copyCount; pixel++)
{
_pixels[pixel] = other.Pixels()[pixel];
}
Dirty();
return *this;
}
T_COLOR_OBJECT* Pixels() const
{
return _pixels;
@ -144,8 +163,8 @@ public:
Dirty();
};
template <typename T_COLOR_FEATURE, typename T_SHADER> void Render(NeoBufferContext<T_COLOR_FEATURE> destBuffer,
T_SHADER& shader)
template <typename T_COLOR_FEATURE, typename T_SHADER>
void Render(NeoBufferContext<T_COLOR_FEATURE> destBuffer, T_SHADER& shader, uint16_t destIndexPixel = 0)
{
if (IsDirty() || shader.IsDirty())
{
@ -159,7 +178,7 @@ public:
for (uint16_t indexPixel = 0; indexPixel < countPixels; indexPixel++)
{
T_COLOR_OBJECT color = shader.Apply(indexPixel, _pixels[indexPixel]);
T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, indexPixel, color);
T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, destIndexPixel + indexPixel, color);
}
shader.ResetDirty();

View File

@ -26,7 +26,7 @@ License along with NeoPixel. If not, see
#pragma once
#ifdef ARDUINO_ARCH_AVR
#if defined(NEOPIXEBUS_NO_STL)
typedef float(*AnimEaseFunction)(float unitValue);
@ -93,7 +93,7 @@ public:
static float CubicOut(float unitValue)
{
unitValue -= 1.0f;
return (unitValue * unitValue * unitValue + 1);
return (unitValue * unitValue * unitValue + 1.0f);
}
static float CubicInOut(float unitValue)
@ -114,7 +114,7 @@ public:
{
unitValue *= 2.0f;
unitValue -= 1.0f;
return (0.5f * (unitValue * unitValue * unitValue) + 1);
return (0.5f * (unitValue * unitValue * unitValue + 1.0f));
}
static float QuarticIn(float unitValue)
@ -125,7 +125,7 @@ public:
static float QuarticOut(float unitValue)
{
unitValue -= 1.0f;
return -(unitValue * unitValue * unitValue * unitValue - 1);
return -(unitValue * unitValue * unitValue * unitValue - 1.0f);
}
static float QuarticInOut(float unitValue)
@ -200,18 +200,18 @@ public:
static float SinusoidalInOut(float unitValue)
{
return -0.5 * (cos(PI * unitValue) - 1.0f);
return -0.5f * (cos(PI * unitValue) - 1.0f);
}
static float SinusoidalCenter(float unitValue)
{
if (unitValue < 0.5f)
{
return (0.5 * sin(PI * unitValue));
return (0.5f * sin(PI * unitValue));
}
else
{
return (-0.5 * (cos(PI * (unitValue-0.5f)) + 1.0f));
return (-0.5f * (cos(PI * (unitValue-0.5f)) + 1.0f));
}
}
@ -277,7 +277,7 @@ public:
unitValue *= 2.0f;
if (unitValue < 1.0f)
{
return (-0.5f * (sqrt(1.0f - unitValue * unitValue) - 1));
return (-0.5f * (sqrt(1.0f - unitValue * unitValue) - 1.0f));
}
else
{
@ -290,19 +290,20 @@ public:
{
unitValue *= 2.0f;
unitValue -= 1.0f;
if (unitValue == 0.0f)
{
return 1.0f;
}
else if (unitValue < 0.0f)
if (unitValue < 0.0f)
{
return (0.5f * sqrt(1.0f - unitValue * unitValue));
}
else
else if (unitValue > 0.0f)
{
unitValue -= 2.0f;
return (-0.5f * (sqrt(1.0f - unitValue * unitValue) - 1.0f ) + 0.5f);
}
else
{
return 1.0f;
}
}
static float Gamma(float unitValue)

View File

@ -0,0 +1,276 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp32.
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
#ifdef ARDUINO_ARCH_ESP32
extern "C"
{
#include <Arduino.h>
#include "Esp32_i2s.h"
}
const uint16_t c_dmaBytesPerPixelBytes = 4;
class NeoEsp32I2sSpeedWs2812x
{
public:
const static uint32_t I2sSampleRate = 100000;
const static uint16_t ByteSendTimeUs = 10;
const static uint16_t ResetTimeUs = 300;
};
class NeoEsp32I2sSpeedSk6812
{
public:
const static uint32_t I2sSampleRate = 100000;
const static uint16_t ByteSendTimeUs = 10;
const static uint16_t ResetTimeUs = 80;
};
class NeoEsp32I2sSpeedTm1814
{
public:
const static uint32_t I2sSampleRate = 100000;
const static uint16_t ByteSendTimeUs = 10;
const static uint16_t ResetTimeUs = 200;
};
class NeoEsp32I2sSpeed800Kbps
{
public:
const static uint32_t I2sSampleRate = 100000;
const static uint16_t ByteSendTimeUs = 10;
const static uint16_t ResetTimeUs = 50;
};
class NeoEsp32I2sSpeed400Kbps
{
public:
const static uint32_t I2sSampleRate = 50000;
const static uint16_t ByteSendTimeUs = 20;
const static uint16_t ResetTimeUs = 50;
};
class NeoEsp32I2sSpeedApa106
{
public:
const static uint32_t I2sSampleRate = 76000;
const static uint16_t ByteSendTimeUs = 14;
const static uint16_t ResetTimeUs = 50;
};
class NeoEsp32I2sBusZero
{
public:
const static uint8_t I2sBusNumber = 0;
};
class NeoEsp32I2sBusOne
{
public:
const static uint8_t I2sBusNumber = 1;
};
class NeoEsp32I2sNotInverted
{
public:
const static bool Inverted = false;
};
class NeoEsp32I2sInverted
{
public:
const static bool Inverted = true;
};
template<typename T_SPEED, typename T_BUS, typename T_INVERT> class NeoEsp32I2sMethodBase
{
public:
NeoEsp32I2sMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_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;
}
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0x00, _sizeData);
_i2sBuffer = static_cast<uint8_t*>(malloc(_i2sBufferSize));
memset(_i2sBuffer, 0x00, _i2sBufferSize);
}
~NeoEsp32I2sMethodBase()
{
while (!IsReadyToUpdate())
{
yield();
}
pinMode(_pin, INPUT);
free(_data);
free(_i2sBuffer);
}
bool IsReadyToUpdate() const
{
return (i2sWriteDone(T_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);
}
void Update(bool)
{
// wait for not actively sending data
while (!IsReadyToUpdate())
{
yield();
}
FillBuffers();
i2sWrite(T_BUS::I2sBusNumber, _i2sBuffer, _i2sBufferSize, false, false);
}
uint8_t* getData() const
{
return _data;
};
size_t getDataSize() const
{
return _sizeData;
}
private:
const size_t _sizeData; // Size of '_data' buffer
const uint8_t _pin; // output pin number
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 FillBuffers()
{
const uint16_t bitpatterns[16] =
{
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
uint16_t* pDma = reinterpret_cast<uint16_t*>(_i2sBuffer);
uint8_t* pEnd = _data + _sizeData;
for (uint8_t* pPixel = _data; pPixel < pEnd; pPixel++)
{
*(pDma++) = bitpatterns[((*pPixel) & 0x0f)];
*(pDma++) = bitpatterns[((*pPixel) >> 4) & 0x0f];
}
}
};
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Ws2812xMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Sk6812Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Tm1814Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0800KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0400KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Apa106Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Ws2812xInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Sk6812InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Tm1814InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0800KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0400KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Apa106InvertedMethod;
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
// (I2S_NUM_MAX == 2)
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Ws2812xMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Sk6812Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Tm1814Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1800KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1400KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Apa106Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Ws2812xInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Sk6812InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Tm1814InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1800KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1400KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Apa106InvertedMethod;
#endif
/* due to a core issue where requests to send aren't consistent, I2s is no longer the default
// I2s Bus 1 method is the default method for Esp32
typedef NeoEsp32I2s1Ws2812xMethod NeoWs2813Method;
typedef NeoEsp32I2s1Ws2812xMethod NeoWs2812xMethod;
typedef NeoEsp32I2s1800KbpsMethod NeoWs2812Method;
typedef NeoEsp32I2s1Ws2812xMethod NeoWs2811Method;
typedef NeoEsp32I2s1Sk6812Method NeoSk6812Method;
typedef NeoEsp32I2s1Tm1814Method NeoTm1814Method;
typedef NeoEsp32I2s1Sk6812Method NeoLc8812Method;
typedef NeoEsp32I2s1Apa106Method NeoApa106Method;
typedef NeoEsp32I2s1Ws2812xMethod Neo800KbpsMethod;
typedef NeoEsp32I2s1400KbpsMethod Neo400KbpsMethod;
typedef NeoEsp32I2s1Ws2812xInvertedMethod NeoWs2813InvertedMethod;
typedef NeoEsp32I2s1Ws2812xInvertedMethod NeoWs2812xInvertedMethod;
typedef NeoEsp32I2s1Ws2812xInvertedMethod NeoWs2811InvertedMethod;
typedef NeoEsp32I2s1800KbpsInvertedMethod NeoWs2812InvertedMethod;
typedef NeoEsp32I2s1Sk6812InvertedMethod NeoSk6812InvertedMethod;
typedef NeoEsp32I2s1Tm1814InvertedMethod NeoTm1814InvertedMethod;
typedef NeoEsp32I2s1Sk6812InvertedMethod NeoLc8812InvertedMethod;
typedef NeoEsp32I2s1Apa106InvertedMethod NeoApa106InvertedMethod;
typedef NeoEsp32I2s1Ws2812xInvertedMethod Neo800KbpsInvertedMethod;
typedef NeoEsp32I2s1400KbpsInvertedMethod Neo400KbpsInvertedMethod;
*/
#endif

View File

@ -0,0 +1,262 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp32.
A BIG thanks to Andreas Merkle for the investigation and implementation of
a workaround to the GCC bug that drops method attributes from template methods
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/>.
-------------------------------------------------------------------------*/
#include "NeoEsp32RmtMethod.h"
#ifdef ARDUINO_ARCH_ESP32
// translate NeoPixelBuffer into RMT buffer
// this is done on the fly so we don't require a send buffer in raw RMT format
// which would be 32x larger than the primary buffer
//
// NOTE: This was moved from the template below to here to workaround a GCC bug
// That bug is that the IRAM_ATTR attribute (any attributes) is lost on template classes.
//
// Further, it was removed from the header to support current Esp32 release
// which will need to be removed when the latest GitHub branchis released
// due to this method will not get inlined this way
//
void NeoEsp32RmtSpeed::_translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num,
const uint32_t rmtBit0,
const uint32_t rmtBit1,
const uint16_t rmtDurationReset)
{
if (src == NULL || dest == NULL)
{
*translated_size = 0;
*item_num = 0;
return;
}
size_t size = 0;
size_t num = 0;
const uint8_t* psrc = static_cast<const uint8_t*>(src);
rmt_item32_t* pdest = dest;
for (;;)
{
uint8_t data = *psrc;
for (uint8_t bit = 0; bit < 8; bit++)
{
pdest->val = (data & 0x80) ? rmtBit1 : rmtBit0;
pdest++;
data <<= 1;
}
num += 8;
size++;
// if this is the last byte we need to adjust the length of the last pulse
if (size >= src_size)
{
// extend the last bits LOW value to include the full reset signal length
pdest--;
pdest->duration1 = rmtDurationReset;
// and stop updating data to send
break;
}
if (num >= wanted_num)
{
// stop updating data to send
break;
}
psrc++;
}
*translated_size = size;
*item_num = num;
}
// these are required due to the linker error with ISRs
// dangerous relocation: l32r: literal placed after use
// https://stackoverflow.com/questions/19532826/what-does-a-dangerous-relocation-error-mean
//
void NeoEsp32RmtSpeedWs2811::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtSpeedWs2812x::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtSpeedSk6812::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtSpeedTm1814::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtSpeed800Kbps::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtSpeed400Kbps::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtSpeedApa106::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtInvertedSpeedWs2811::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtInvertedSpeedWs2812x::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtInvertedSpeedSk6812::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtInvertedSpeedTm1814::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtInvertedSpeed800Kbps::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtInvertedSpeed400Kbps::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
void NeoEsp32RmtInvertedSpeedApa106::Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num)
{
_translate(src, dest, src_size, wanted_num, translated_size, item_num,
RmtBit0, RmtBit1, RmtDurationReset);
}
#endif

View File

@ -0,0 +1,668 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp32.
A BIG thanks to Andreas Merkle for the investigation and implementation of
a workaround to the GCC bug that drops method attributes from template methods
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
#ifdef ARDUINO_ARCH_ESP32
/* General Reference documentation for the APIs used in this implementation
LOW LEVEL: (what is actually used)
DOCS: https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html
EXAMPLE: https://github.com/espressif/esp-idf/blob/826ff7186ae07dc81e960a8ea09ebfc5304bfb3b/examples/peripherals/rmt_tx/main/rmt_tx_main.c
HIGHER LEVEL:
NO TRANSLATE SUPPORT so this was not used
NOTE: https://github.com/espressif/arduino-esp32/commit/50d142950d229b8fabca9b749dc4a5f2533bc426
Esp32-hal-rmt.h
Esp32-hal-rmt.c
*/
#include <Arduino.h>
extern "C"
{
#include <driver/rmt.h>
}
class NeoEsp32RmtSpeed
{
public:
// ClkDiv of 2 provides for good resolution and plenty of reset resolution; but
// a ClkDiv of 1 will provide enough space for the longest reset and does show
// little better pulse accuracy
const static uint8_t RmtClockDivider = 2;
inline constexpr static uint32_t FromNs(uint32_t ns)
{
return ns / NsPerRmtTick;
}
protected:
const static uint32_t RmtCpu = 80000000L; // 80 mhz RMT clock
const static uint32_t NsPerSecond = 1000000000L;
const static uint32_t RmtTicksPerSecond = (RmtCpu / RmtClockDivider);
const static uint32_t NsPerRmtTick = (NsPerSecond / RmtTicksPerSecond); // about 25
static void IRAM_ATTR _translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num,
const uint32_t rmtBit0,
const uint32_t rmtBit1,
const uint16_t rmtDurationReset);
};
class NeoEsp32RmtSpeedBase : public NeoEsp32RmtSpeed
{
public:
// this is used rather than the rmt_item32_t as you can't correctly initialize
// it as a static constexpr within the template
inline constexpr static uint32_t Item32Val(uint16_t nsHigh, uint16_t nsLow)
{
return (FromNs(nsLow) << 16) | (1 << 15) | (FromNs(nsHigh));
}
const static rmt_idle_level_t IdleLevel = RMT_IDLE_LEVEL_LOW;
};
class NeoEsp32RmtInvertedSpeedBase : public NeoEsp32RmtSpeed
{
public:
// this is used rather than the rmt_item32_t as you can't correctly initialize
// it as a static constexpr within the template
inline constexpr static uint32_t Item32Val(uint16_t nsHigh, uint16_t nsLow)
{
return (FromNs(nsLow) << 16) | (1 << 31) | (FromNs(nsHigh));
}
const static rmt_idle_level_t IdleLevel = RMT_IDLE_LEVEL_HIGH;
};
class NeoEsp32RmtSpeedWs2811 : public NeoEsp32RmtSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(300, 950);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(900, 350);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(300000); // 300us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtSpeedWs2812x : public NeoEsp32RmtSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(400, 850);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(800, 450);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(300000); // 300us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtSpeedSk6812 : public NeoEsp32RmtSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(400, 850);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(800, 450);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(80000); // 80us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
// normal is inverted signal
class NeoEsp32RmtSpeedTm1814 : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(360, 890);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(720, 530);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(200000); // 200us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtSpeed800Kbps : public NeoEsp32RmtSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(400, 850);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(800, 450);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(50000); // 50us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtSpeed400Kbps : public NeoEsp32RmtSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(800, 1700);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(1600, 900);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(50000); // 50us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
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 uint16_t RmtDurationReset = FromNs(50000); // 50us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtInvertedSpeedWs2811 : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(300, 950);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(900, 350);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(300000); // 300us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtInvertedSpeedWs2812x : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(400, 850);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(800, 450);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(300000); // 300us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtInvertedSpeedSk6812 : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(400, 850);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(800, 450);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(80000); // 80us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
// normal is inverted signal
class NeoEsp32RmtInvertedSpeedTm1814 : public NeoEsp32RmtSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(360, 890);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(720, 530);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(200000); // 200us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtInvertedSpeed800Kbps : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(400, 850);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(800, 450);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(50000); // 50us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtInvertedSpeed400Kbps : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static DRAM_ATTR uint32_t RmtBit0 = Item32Val(800, 1700);
const static DRAM_ATTR uint32_t RmtBit1 = Item32Val(1600, 900);
const static DRAM_ATTR uint16_t RmtDurationReset = FromNs(50000); // 50us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
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 uint16_t RmtDurationReset = FromNs(50000); // 50us
static void IRAM_ATTR Translate(const void* src,
rmt_item32_t* dest,
size_t src_size,
size_t wanted_num,
size_t* translated_size,
size_t* item_num);
};
class NeoEsp32RmtChannel0
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_0;
};
class NeoEsp32RmtChannel1
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_1;
};
class NeoEsp32RmtChannel2
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_2;
};
class NeoEsp32RmtChannel3
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_3;
};
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
class NeoEsp32RmtChannel4
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_4;
};
class NeoEsp32RmtChannel5
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_5;
};
class NeoEsp32RmtChannel6
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_6;
};
class NeoEsp32RmtChannel7
{
public:
const static rmt_channel_t RmtChannelNumber = RMT_CHANNEL_7;
};
#endif
template<typename T_SPEED, typename T_CHANNEL> class NeoEsp32RmtMethodBase
{
public:
NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize),
_pin(pin)
{
_dataEditing = static_cast<uint8_t*>(malloc(_sizeData));
memset(_dataEditing, 0x00, _sizeData);
_dataSending = static_cast<uint8_t*>(malloc(_sizeData));
// no need to initialize it, it gets overwritten on every send
}
~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(rmt_driver_uninstall(T_CHANNEL::RmtChannelNumber));
free(_dataEditing);
free(_dataSending);
}
bool IsReadyToUpdate() const
{
return (ESP_OK == rmt_wait_tx_done(T_CHANNEL::RmtChannelNumber, 0));
}
void Initialize()
{
rmt_config_t config;
config.rmt_mode = RMT_MODE_TX;
config.channel = T_CHANNEL::RmtChannelNumber;
config.gpio_num = static_cast<gpio_num_t>(_pin);
config.mem_block_num = 1;
config.tx_config.loop_en = false;
config.tx_config.idle_output_en = true;
config.tx_config.idle_level = T_SPEED::IdleLevel;
config.tx_config.carrier_en = false;
config.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
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));
}
void Update(bool maintainBufferConsistency)
{
// 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)))
{
// 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));
if (maintainBufferConsistency)
{
// copy editing to sending,
// this maintains the contract that "colors present before will
// be the same after", otherwise GetPixelColor will be inconsistent
memcpy(_dataSending, _dataEditing, _sizeData);
}
// swap so the user can modify without affecting the async operation
std::swap(_dataSending, _dataEditing);
}
}
uint8_t* getData() const
{
return _dataEditing;
};
size_t getDataSize() const
{
return _sizeData;
}
private:
const size_t _sizeData; // Size of '_data*' buffers
const uint8_t _pin; // output pin number
// 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
};
// normal
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedTm1814, NeoEsp32RmtChannel0> NeoEsp32Rmt0Tm1814Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel0> NeoEsp32Rmt0Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel0> NeoEsp32Rmt0800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel0> NeoEsp32Rmt0400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel1> NeoEsp32Rmt1Ws2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel1> NeoEsp32Rmt1Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel1> NeoEsp32Rmt1Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedTm1814, NeoEsp32RmtChannel1> NeoEsp32Rmt1Tm1814Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel1> NeoEsp32Rmt1Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel1> NeoEsp32Rmt1800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel1> NeoEsp32Rmt1400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel2> NeoEsp32Rmt2Ws2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel2> NeoEsp32Rmt2Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel2> NeoEsp32Rmt2Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedTm1814, NeoEsp32RmtChannel2> NeoEsp32Rmt2Tm1814Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel2> NeoEsp32Rmt2Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel2> NeoEsp32Rmt2800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel2> NeoEsp32Rmt2400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel3> NeoEsp32Rmt3Ws2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel3> NeoEsp32Rmt3Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel3> NeoEsp32Rmt3Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedTm1814, NeoEsp32RmtChannel3> NeoEsp32Rmt3Tm1814Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel3> NeoEsp32Rmt3Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel3> NeoEsp32Rmt3800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel3> NeoEsp32Rmt3400KbpsMethod;
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
// (RMT_CHANNEL_MAX == 8)
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel4> NeoEsp32Rmt4Ws2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel4> NeoEsp32Rmt4Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel4> NeoEsp32Rmt4Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedTm1814, NeoEsp32RmtChannel4> NeoEsp32Rmt4Tm1814Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel4> NeoEsp32Rmt4Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel4> NeoEsp32Rmt4800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel4> NeoEsp32Rmt4400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel5> NeoEsp32Rmt5Ws2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel5> NeoEsp32Rmt5Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel5> NeoEsp32Rmt5Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedTm1814, NeoEsp32RmtChannel5> NeoEsp32Rmt5Tm1814Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel5> NeoEsp32Rmt5Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel5> NeoEsp32Rmt5800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel5> NeoEsp32Rmt5400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel6> NeoEsp32Rmt6Ws2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel6> NeoEsp32Rmt6Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel6> NeoEsp32Rmt6Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedTm1814, NeoEsp32RmtChannel6> NeoEsp32Rmt6Tm1814Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel6> NeoEsp32Rmt6Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel6> NeoEsp32Rmt6800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel6> NeoEsp32Rmt6400KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtChannel7> NeoEsp32Rmt7Ws2811Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel7> NeoEsp32Rmt7Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel7> NeoEsp32Rmt7Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedTm1814, NeoEsp32RmtChannel7> NeoEsp32Rmt7Tm1814Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel7> NeoEsp32Rmt7Apa106Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7400KbpsMethod;
#endif
// inverted
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedTm1814, NeoEsp32RmtChannel0> NeoEsp32Rmt0Tm1814InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel0> NeoEsp32Rmt0Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel0> NeoEsp32Rmt0800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel0> NeoEsp32Rmt0400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel1> NeoEsp32Rmt1Ws2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel1> NeoEsp32Rmt1Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel1> NeoEsp32Rmt1Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedTm1814, NeoEsp32RmtChannel1> NeoEsp32Rmt1Tm1814InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel1> NeoEsp32Rmt1Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel1> NeoEsp32Rmt1800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel1> NeoEsp32Rmt1400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel2> NeoEsp32Rmt2Ws2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel2> NeoEsp32Rmt2Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel2> NeoEsp32Rmt2Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedTm1814, NeoEsp32RmtChannel2> NeoEsp32Rmt2Tm1814InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel2> NeoEsp32Rmt2Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel2> NeoEsp32Rmt2800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel2> NeoEsp32Rmt2400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel3> NeoEsp32Rmt3Ws2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel3> NeoEsp32Rmt3Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel3> NeoEsp32Rmt3Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedTm1814, NeoEsp32RmtChannel3> NeoEsp32Rmt3Tm1814InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel3> NeoEsp32Rmt3Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel3> NeoEsp32Rmt3800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel3> NeoEsp32Rmt3400KbpsInvertedMethod;
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
// (RMT_CHANNEL_MAX == 8)
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel4> NeoEsp32Rmt4Ws2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel4> NeoEsp32Rmt4Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel4> NeoEsp32Rmt4Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedTm1814, NeoEsp32RmtChannel4> NeoEsp32Rmt4Tm1814InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel4> NeoEsp32Rmt4Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel4> NeoEsp32Rmt4800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel4> NeoEsp32Rmt4400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel5> NeoEsp32Rmt5Ws2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel5> NeoEsp32Rmt5Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel5> NeoEsp32Rmt5Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedTm1814, NeoEsp32RmtChannel5> NeoEsp32Rmt5Tm1814InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel5> NeoEsp32Rmt5Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel5> NeoEsp32Rmt5800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel5> NeoEsp32Rmt5400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel6> NeoEsp32Rmt6Ws2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel6> NeoEsp32Rmt6Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel6> NeoEsp32Rmt6Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedTm1814, NeoEsp32RmtChannel6> NeoEsp32Rmt6Tm1814InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel6> NeoEsp32Rmt6Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel6> NeoEsp32Rmt6800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel6> NeoEsp32Rmt6400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2811, NeoEsp32RmtChannel7> NeoEsp32Rmt7Ws2811InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel7> NeoEsp32Rmt7Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel7> NeoEsp32Rmt7Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedTm1814, NeoEsp32RmtChannel7> NeoEsp32Rmt7Tm1814InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel7> NeoEsp32Rmt7Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7400KbpsInvertedMethod;
#endif
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
// (RMT_CHANNEL_MAX == 8)
// due to a core issue where requests to send aren't consistent with I2s, RMT ch6 is temporarily the default
// RMT channel 6 method is the default method for Esp32
typedef NeoEsp32Rmt6Ws2812xMethod NeoWs2813Method;
typedef NeoEsp32Rmt6Ws2812xMethod NeoWs2812xMethod;
typedef NeoEsp32Rmt6800KbpsMethod NeoWs2812Method;
typedef NeoEsp32Rmt6Ws2812xMethod NeoWs2811Method;
typedef NeoEsp32Rmt6Sk6812Method NeoSk6812Method;
typedef NeoEsp32Rmt6Tm1814Method NeoTm1814Method;
typedef NeoEsp32Rmt6Sk6812Method NeoLc8812Method;
typedef NeoEsp32Rmt6Apa106Method NeoApa106Method;
typedef NeoEsp32Rmt6Ws2812xMethod Neo800KbpsMethod;
typedef NeoEsp32Rmt6400KbpsMethod Neo400KbpsMethod;
typedef NeoEsp32Rmt6Ws2812xInvertedMethod NeoWs2813InvertedMethod;
typedef NeoEsp32Rmt6Ws2812xInvertedMethod NeoWs2812xInvertedMethod;
typedef NeoEsp32Rmt6Ws2812xInvertedMethod NeoWs2811InvertedMethod;
typedef NeoEsp32Rmt6800KbpsInvertedMethod NeoWs2812InvertedMethod;
typedef NeoEsp32Rmt6Sk6812InvertedMethod NeoSk6812InvertedMethod;
typedef NeoEsp32Rmt6Tm1814InvertedMethod NeoTm1814InvertedMethod;
typedef NeoEsp32Rmt6Sk6812InvertedMethod NeoLc8812InvertedMethod;
typedef NeoEsp32Rmt6Apa106InvertedMethod NeoApa106InvertedMethod;
typedef NeoEsp32Rmt6Ws2812xInvertedMethod Neo800KbpsInvertedMethod;
typedef NeoEsp32Rmt6400KbpsInvertedMethod Neo400KbpsInvertedMethod;
#else
// due to a core issue where requests to send aren't consistent with I2s, RMT ch3 is temporarily the default
// RMT channel 3 method is the default method for Esp32S2
typedef NeoEsp32Rmt3Ws2812xMethod NeoWs2813Method;
typedef NeoEsp32Rmt3Ws2812xMethod NeoWs2812xMethod;
typedef NeoEsp32Rmt3800KbpsMethod NeoWs2812Method;
typedef NeoEsp32Rmt3Ws2812xMethod NeoWs2811Method;
typedef NeoEsp32Rmt3Sk6812Method NeoSk6812Method;
typedef NeoEsp32Rmt3Tm1814Method NeoTm1814Method;
typedef NeoEsp32Rmt3Sk6812Method NeoLc8812Method;
typedef NeoEsp32Rmt3Apa106Method NeoApa106Method;
typedef NeoEsp32Rmt3Ws2812xMethod Neo800KbpsMethod;
typedef NeoEsp32Rmt3400KbpsMethod Neo400KbpsMethod;
typedef NeoEsp32Rmt3Ws2812xInvertedMethod NeoWs2813InvertedMethod;
typedef NeoEsp32Rmt3Ws2812xInvertedMethod NeoWs2812xInvertedMethod;
typedef NeoEsp32Rmt3Ws2812xInvertedMethod NeoWs2811InvertedMethod;
typedef NeoEsp32Rmt3800KbpsInvertedMethod NeoWs2812InvertedMethod;
typedef NeoEsp32Rmt3Sk6812InvertedMethod NeoSk6812InvertedMethod;
typedef NeoEsp32Rmt3Tm1814InvertedMethod NeoTm1814InvertedMethod;
typedef NeoEsp32Rmt3Sk6812InvertedMethod NeoLc8812InvertedMethod;
typedef NeoEsp32Rmt3Apa106InvertedMethod NeoApa106InvertedMethod;
typedef NeoEsp32Rmt3Ws2812xInvertedMethod Neo800KbpsInvertedMethod;
typedef NeoEsp32Rmt3400KbpsInvertedMethod Neo400KbpsInvertedMethod;
#endif
#endif

View File

@ -65,7 +65,43 @@ struct slc_queue_item
uint32 next_link_ptr;
};
class NeoEsp8266DmaSpeed800KbpsBase
class NeoEsp8266DmaSpeedBase
{
public:
static const uint8_t Level = 0x00;
static uint16_t Convert(uint8_t value)
{
const uint16_t bitpatterns[16] =
{
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
return bitpatterns[value];
}
};
class NeoEsp8266DmaInvertedSpeedBase
{
public:
static const uint8_t Level = 0xFF;
static uint16_t Convert(uint8_t value)
{
const uint16_t bitpatterns[16] =
{
0b0111011101110111, 0b0111011101110001, 0b0111011100010111, 0b0111011100010001,
0b0111000101110111, 0b0111000101110001, 0b0111000100010111, 0b0111000100010001,
0b0001011101110111, 0b0001011101110001, 0b0001011100010111, 0b0001011100010001,
0b0001000101110111, 0b0001000101110001, 0b0001000100010111, 0b0001000100010001,
};
return bitpatterns[value];
}
};
class NeoEsp8266DmaSpeed800KbpsBase : public NeoEsp8266DmaSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 3;
@ -85,13 +121,19 @@ public:
const static uint32_t ResetTimeUs = 80;
};
class NeoEsp8266DmaInvertedSpeedTm1814 : public NeoEsp8266DmaSpeed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 200;
};
class NeoEsp8266DmaSpeed800Kbps : public NeoEsp8266DmaSpeed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaSpeed400Kbps
class NeoEsp8266DmaSpeed400Kbps : public NeoEsp8266DmaSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 6;
@ -100,13 +142,65 @@ public:
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaSpeedApa106
class NeoEsp8266DmaSpeedApa106 : public NeoEsp8266DmaSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 4;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ByteSendTimeUs = 17; // us it takes to send a single pixel element
const static uint32_t ResetTimeUs = 50;
const static uint32_t I2sClockDivisor = 4;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ByteSendTimeUs = 17; // us it takes to send a single pixel element
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaInvertedSpeed800KbpsBase : public NeoEsp8266DmaInvertedSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 3;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed
};
class NeoEsp8266DmaInvertedSpeedWs2812x : public NeoEsp8266DmaInvertedSpeed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 300;
};
class NeoEsp8266DmaInvertedSpeedSk6812 : public NeoEsp8266DmaInvertedSpeed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 80;
};
class NeoEsp8266DmaSpeedTm1814 : public NeoEsp8266DmaInvertedSpeed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 200;
};
class NeoEsp8266DmaInvertedSpeed800Kbps : public NeoEsp8266DmaInvertedSpeed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaInvertedSpeed400Kbps : public NeoEsp8266DmaInvertedSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 6;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ByteSendTimeUs = 20; // us it takes to send a single pixel element at 400khz speed
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaInvertedSpeedApa106 : public NeoEsp8266DmaInvertedSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 4;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ByteSendTimeUs = 17; // us it takes to send a single pixel element
const static uint32_t ResetTimeUs = 50;
};
enum NeoDmaState
@ -123,22 +217,23 @@ const uint8_t c_I2sPin = 3; // due to I2S hardware, the pin used is restricted t
template<typename T_SPEED> class NeoEsp8266DmaMethodBase
{
public:
NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize)
NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize)
{
uint16_t dmaPixelSize = c_dmaBytesPerPixelBytes * elementSize;
uint16_t dmaSettingsSize = c_dmaBytesPerPixelBytes * settingsSize;
_pixelsSize = pixelCount * elementSize;
_i2sBufferSize = pixelCount * dmaPixelSize;
_i2sBufferSize = pixelCount * dmaPixelSize + dmaSettingsSize;
_pixels = (uint8_t*)malloc(_pixelsSize);
memset(_pixels, 0x00, _pixelsSize);
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0x00, _sizeData);
_i2sBuffer = (uint8_t*)malloc(_i2sBufferSize);
memset(_i2sBuffer, 0x00, _i2sBufferSize);
_i2sBuffer = static_cast<uint8_t*>(malloc(_i2sBufferSize));
memset(_i2sBuffer, T_SPEED::Level, _i2sBufferSize);
// _i2sBuffer[0] = 0b11101000; // debug, 1 bit then 0 bit
memset(_i2sZeroes, 0x00, sizeof(_i2sZeroes));
memset(_i2sZeroes, T_SPEED::Level, sizeof(_i2sZeroes));
_is2BufMaxBlockSize = (c_maxDmaBlockSize / dmaPixelSize) * dmaPixelSize;
@ -148,7 +243,8 @@ public:
s_this = this; // store this for the ISR
}
NeoEsp8266DmaMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) : NeoEsp8266DmaMethodBase(pixelCount, elementSize)
NeoEsp8266DmaMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
NeoEsp8266DmaMethodBase(pixelCount, elementSize, settingsSize)
{
}
@ -174,7 +270,7 @@ public:
s_this = nullptr;
pinMode(c_I2sPin, INPUT);
free(_pixels);
free(_data);
free(_i2sBuffer);
free(_i2sBufDesc);
}
@ -307,23 +403,23 @@ public:
_dmaState = NeoDmaState_Pending;
}
uint8_t* getPixels() const
uint8_t* getData() const
{
return _pixels;
return _data;
};
size_t getPixelsSize() const
size_t getDataSize() const
{
return _pixelsSize;
return _sizeData;
}
private:
static NeoEsp8266DmaMethodBase* s_this; // for the ISR
size_t _pixelsSize; // Size of '_pixels' buffer
uint8_t* _pixels; // Holds LED color values
const size_t _sizeData; // Size of '_data' buffer
uint8_t* _data; // Holds LED color values
uint32_t _i2sBufferSize; // total size of _i2sBuffer
size_t _i2sBufferSize; // total size of _i2sBuffer
uint8_t* _i2sBuffer; // holds the DMA buffer that is referenced by _i2sBufDesc
// normally 24 bytes creates the minimum 50us latch per spec, but
@ -341,7 +437,7 @@ private:
// handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
// descriptor has the 'EOF' field set to 1.
// in the case of this code, the second to last state descriptor
volatile static void ICACHE_RAM_ATTR i2s_slc_isr(void)
static void ICACHE_RAM_ATTR i2s_slc_isr(void)
{
ETS_SLC_INTR_DISABLE();
@ -392,20 +488,12 @@ private:
void FillBuffers()
{
const uint16_t bitpatterns[16] =
{
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
uint16_t* pDma = (uint16_t*)_i2sBuffer;
uint8_t* pPixelsEnd = _pixels + _pixelsSize;
for (uint8_t* pPixel = _pixels; pPixel < pPixelsEnd; pPixel++)
uint8_t* pEnd = _data + _sizeData;
for (uint8_t* pData = _data; pData < pEnd; pData++)
{
*(pDma++) = bitpatterns[((*pPixel) & 0x0f)];
*(pDma++) = bitpatterns[((*pPixel) >> 4) & 0x0f];
*(pDma++) = T_SPEED::Convert(((*pData) & 0x0f));
*(pDma++) = T_SPEED::Convert(((*pData) >> 4) & 0x0f);
}
}
@ -432,29 +520,54 @@ private:
uint32_t getPixelTime() const
{
return (T_SPEED::ByteSendTimeUs * this->_pixelsSize);
return (T_SPEED::ByteSendTimeUs * this->_sizeData);
};
};
template<typename T_SPEED>
NeoEsp8266DmaMethodBase<T_SPEED>* NeoEsp8266DmaMethodBase<T_SPEED>::s_this;
// normal
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedWs2812x> NeoEsp8266DmaWs2812xMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedSk6812> NeoEsp8266DmaSk6812Method;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedTm1814> NeoEsp8266DmaTm1814Method;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeed800Kbps> NeoEsp8266Dma800KbpsMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeed400Kbps> NeoEsp8266Dma400KbpsMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedApa106> NeoEsp8266DmaApa106Method;
// inverted
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedWs2812x> NeoEsp8266DmaInvertedWs2812xMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedSk6812> NeoEsp8266DmaInvertedSk6812Method;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedTm1814> NeoEsp8266DmaInvertedTm1814Method;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeed800Kbps> NeoEsp8266DmaInverted800KbpsMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeed400Kbps> NeoEsp8266DmaInverted400KbpsMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedApa106> NeoEsp8266DmaInvertedApa106Method;
// Dma method is the default method for Esp8266
typedef NeoEsp8266DmaWs2812xMethod NeoWs2813Method;
typedef NeoEsp8266DmaWs2812xMethod NeoWs2812xMethod;
typedef NeoEsp8266Dma800KbpsMethod NeoWs2812Method;
typedef NeoEsp8266DmaWs2812xMethod NeoWs2811Method;
typedef NeoEsp8266DmaSk6812Method NeoSk6812Method;
typedef NeoEsp8266DmaTm1814Method NeoTm1814Method;
typedef NeoEsp8266DmaSk6812Method NeoLc8812Method;
typedef NeoEsp8266DmaApa106Method NeoApa106Method;
typedef NeoEsp8266DmaWs2812xMethod Neo800KbpsMethod;
typedef NeoEsp8266Dma400KbpsMethod Neo400KbpsMethod;
// inverted
typedef NeoEsp8266DmaInvertedWs2812xMethod NeoWs2813InvertedMethod;
typedef NeoEsp8266DmaInvertedWs2812xMethod NeoWs2812xInvertedMethod;
typedef NeoEsp8266DmaInverted800KbpsMethod NeoWs2812InvertedMethod;
typedef NeoEsp8266DmaInvertedWs2812xMethod NeoWs2811InvertedMethod;
typedef NeoEsp8266DmaInvertedSk6812Method NeoSk6812InvertedMethod;
typedef NeoEsp8266DmaInvertedTm1814Method NeoTm1814InvertedMethod;
typedef NeoEsp8266DmaInvertedSk6812Method NeoLc8812InvertedMethod;
typedef NeoEsp8266DmaInvertedApa106Method NeoApa106InvertedMethod;
typedef NeoEsp8266DmaInvertedWs2812xMethod Neo800KbpsInvertedMethod;
typedef NeoEsp8266DmaInverted400KbpsMethod Neo400KbpsInvertedMethod;
#endif

View File

@ -33,7 +33,7 @@ extern "C"
}
const volatile uint8_t* ICACHE_RAM_ATTR NeoEsp8266UartContext::FillUartFifo(uint8_t uartNum,
const volatile uint8_t* pixels,
const volatile uint8_t* start,
const volatile uint8_t* end)
{
// Remember: UARTs send less significant bit (LSB) first so
@ -47,19 +47,19 @@ const volatile uint8_t* ICACHE_RAM_ATTR NeoEsp8266UartContext::FillUartFifo(uint
0b000100, // On wire: 1 110 111 0 [NeoPixel reads 11]
};
uint8_t avail = (UART_TX_FIFO_SIZE - GetTxFifoLength(uartNum)) / 4;
if (end - pixels > avail)
if (end - start > avail)
{
end = pixels + avail;
end = start + avail;
}
while (pixels < end)
while (start < end)
{
uint8_t subpix = *pixels++;
uint8_t subpix = *start++;
Enqueue(uartNum, _uartData[(subpix >> 6) & 0x3]);
Enqueue(uartNum, _uartData[(subpix >> 4) & 0x3]);
Enqueue(uartNum, _uartData[(subpix >> 2) & 0x3]);
Enqueue(uartNum, _uartData[subpix & 0x3]);
}
return pixels;
return start;
}
volatile NeoEsp8266UartInterruptContext* NeoEsp8266UartInterruptContext::s_uartInteruptContext[] = { nullptr, nullptr };

View File

@ -0,0 +1,514 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp8266 UART hardware
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
#ifdef ARDUINO_ARCH_ESP8266
#include <Arduino.h>
// this template method class is used to track the data being sent on the uart
// when using the default serial ISR installed by the core
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
//
class NeoEsp8266UartContext
{
public:
// Gets the number of bytes waiting in the TX FIFO
static inline uint8_t ICACHE_RAM_ATTR GetTxFifoLength(uint8_t uartNum)
{
return (USS(uartNum) >> USTXC) & 0xff;
}
// Append a byte to the TX FIFO
static inline void ICACHE_RAM_ATTR Enqueue(uint8_t uartNum, uint8_t value)
{
USF(uartNum) = value;
}
static const volatile uint8_t* ICACHE_RAM_ATTR FillUartFifo(uint8_t uartNum,
const volatile uint8_t* start,
const volatile uint8_t* end);
};
// this template method class is used to track the data being sent on the uart
// when using our own UART ISR
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
//
class NeoEsp8266UartInterruptContext : NeoEsp8266UartContext
{
public:
NeoEsp8266UartInterruptContext() :
_asyncBuff(nullptr),
_asyncBuffEnd(nullptr)
{
}
bool IsSending()
{
return (_asyncBuff != _asyncBuffEnd);
}
void StartSending(uint8_t uartNum, uint8_t* start, uint8_t* end);
void Attach(uint8_t uartNum);
void Detach(uint8_t uartNum);
private:
volatile const uint8_t* _asyncBuff;
volatile const uint8_t* _asyncBuffEnd;
volatile static NeoEsp8266UartInterruptContext* s_uartInteruptContext[2];
static void ICACHE_RAM_ATTR Isr(void* param);
};
// this template feature class is used a base for all others and contains
// common methods
//
class UartFeatureBase
{
protected:
static void ConfigUart(uint8_t uartNum, bool invert)
{
// clear all invert bits
USC0(uartNum) &= ~((1 << UCDTRI) | (1 << UCRTSI) | (1 << UCTXI) | (1 << UCDSRI) | (1 << UCCTSI) | (1 << UCRXI));
if (!invert)
{
// For normal operations,
// Invert the TX voltage associated with logic level so:
// - A logic level 0 will generate a Vcc signal
// - A logic level 1 will generate a Gnd signal
USC0(uartNum) |= (1 << UCTXI);
}
}
};
// this template feature class is used to define the specifics for uart0
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
//
class UartFeature0 : UartFeatureBase
{
public:
static const uint32_t Index = 0;
static void Init(uint32_t baud, bool invert)
{
// Configure the serial line with 1 start bit (0), 6 data bits and 1 stop bit (1)
Serial.begin(baud, SERIAL_6N1, SERIAL_TX_ONLY);
ConfigUart(Index, invert);
}
};
// this template feature class is used to define the specifics for uart1
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
//
class UartFeature1 : UartFeatureBase
{
public:
static const uint32_t Index = 1;
static void Init(uint32_t baud, bool invert)
{
// Configure the serial line with 1 start bit (0), 6 data bits and 1 stop bit (1)
Serial1.begin(baud, SERIAL_6N1, SERIAL_TX_ONLY);
ConfigUart(Index, invert);
}
};
// this template method class is used a base for all others and contains
// common properties and methods
//
// used by NeoEsp8266Uart and NeoEsp8266AsyncUart
//
class NeoEsp8266UartBase
{
protected:
const size_t _sizeData; // Size of '_data' buffer below
uint8_t* _data; // Holds LED color values
uint32_t _startTime; // Microsecond count when last update started
NeoEsp8266UartBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize)
{
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0x00, _sizeData);
}
~NeoEsp8266UartBase()
{
free(_data);
}
};
// this template method class is used to glue uart feature and context for
// synchronous uart method
//
// used by NeoEsp8266UartMethodBase
//
template<typename T_UARTFEATURE, typename T_UARTCONTEXT> class NeoEsp8266Uart : public NeoEsp8266UartBase
{
protected:
NeoEsp8266Uart(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
NeoEsp8266UartBase(pixelCount, elementSize, settingsSize)
{
}
~NeoEsp8266Uart()
{
// Wait until the TX fifo is empty. This way we avoid broken frames
// when destroying & creating a NeoPixelBus to change its length.
while (T_UARTCONTEXT::GetTxFifoLength(T_UARTFEATURE::Index) > 0)
{
yield();
}
}
void InitializeUart(uint32_t uartBaud, bool invert)
{
T_UARTFEATURE::Init(uartBaud, invert);
}
void UpdateUart(bool)
{
// Since the UART can finish sending queued bytes in the FIFO in
// the background, instead of waiting for the FIFO to flush
// we annotate the start time of the frame so we can calculate
// when it will finish.
_startTime = micros();
// Then keep filling the FIFO until done
const uint8_t* ptr = _data;
const uint8_t* end = ptr + _sizeData;
while (ptr != end)
{
ptr = const_cast<uint8_t*>(T_UARTCONTEXT::FillUartFifo(T_UARTFEATURE::Index, ptr, end));
}
}
};
// this template method class is used to glue uart feature and context for
// asynchronously uart method
//
// This UART controller uses two buffers that are swapped in every call to
// NeoPixelBus.Show(). One buffer contains the data that is being sent
// asynchronosly and another buffer contains the data that will be send
// in the next call to NeoPixelBus.Show().
//
// Therefore, the result of NeoPixelBus.Pixels() is invalidated after
// every call to NeoPixelBus.Show() and must not be cached.
//
// used by NeoEsp8266UartMethodBase
//
template<typename T_UARTFEATURE, typename T_UARTCONTEXT> class NeoEsp8266AsyncUart : public NeoEsp8266UartBase
{
protected:
NeoEsp8266AsyncUart(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
NeoEsp8266UartBase(pixelCount, elementSize, settingsSize)
{
_dataSending = static_cast<uint8_t*>(malloc(_sizeData));
}
~NeoEsp8266AsyncUart()
{
// Remember: the UART interrupt can be sending data from _dataSending in the background
while (_context.IsSending())
{
yield();
}
// detach context, which will disable intr, may disable ISR
_context.Detach(T_UARTFEATURE::Index);
free(_dataSending);
}
void ICACHE_RAM_ATTR InitializeUart(uint32_t uartBaud, bool invert)
{
T_UARTFEATURE::Init(uartBaud, invert);
// attach the context, which will enable the ISR
_context.Attach(T_UARTFEATURE::Index);
}
void UpdateUart(bool maintainBufferConsistency)
{
// Instruct ESP8266 hardware uart to send the pixels asynchronously
_context.StartSending(T_UARTFEATURE::Index,
_data,
_data + _sizeData);
// Annotate when we started to send bytes, so we can calculate when we are ready to send again
_startTime = micros();
if (maintainBufferConsistency)
{
// copy editing to sending,
// this maintains the contract that "colors present before will
// be the same after", otherwise GetPixelColor will be inconsistent
memcpy(_dataSending, _data, _sizeData);
}
// swap so the user can modify without affecting the async operation
std::swap(_dataSending, _data);
}
private:
T_UARTCONTEXT _context;
uint8_t* _dataSending; // Holds a copy of LED color values taken when UpdateUart began
};
class NeoEsp8266UartSpeed800KbpsBase
{
public:
static const uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed
static const uint32_t UartBaud = 3200000; // 800mhz, 4 serial bytes per NeoByte
};
// NeoEsp8266UartSpeedWs2813 contains the timing constants used to get NeoPixelBus running with the Ws2813
class NeoEsp8266UartSpeedWs2812x : public NeoEsp8266UartSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 300; // us between data send bursts to reset for next update
};
class NeoEsp8266UartSpeedSk6812 : public NeoEsp8266UartSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 80; // us between data send bursts to reset for next update
};
class NeoEsp8266UartSpeedTm1814 : public NeoEsp8266UartSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 200; // us between data send bursts to reset for next update
};
// NeoEsp8266UartSpeed800Kbps contains the timing constant used to get NeoPixelBus running at 800Khz
class NeoEsp8266UartSpeed800Kbps : public NeoEsp8266UartSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update
};
// NeoEsp8266UartSpeed400Kbps contains the timing constant used to get NeoPixelBus running at 400Khz
class NeoEsp8266UartSpeed400Kbps
{
public:
static const uint32_t ByteSendTimeUs = 20; // us it takes to send a single pixel element at 400khz speed
static const uint32_t UartBaud = 1600000; // 400mhz, 4 serial bytes per NeoByte
static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update
};
// NeoEsp8266UartSpeedApa106 contains the timing constant used to get NeoPixelBus running for Apa106
// Pulse cycle = 1.71 = 1.368 longer than normal, 0.731 slower, NeoEsp8266UartSpeedApa1066
class NeoEsp8266UartSpeedApa106
{
public:
static const uint32_t ByteSendTimeUs = 14; // us it takes to send a single pixel element at 400khz speed
static const uint32_t UartBaud = 2339181; // APA106 pulse cycle of 1.71us, 4 serial bytes per NeoByte
static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update
};
class NeoEsp8266UartNotInverted
{
public:
const static bool Inverted = false;
};
class NeoEsp8266UartInverted
{
public:
const static bool Inverted = true;
};
// NeoEsp8266UartMethodBase is a light shell arround NeoEsp8266Uart or NeoEsp8266AsyncUart that
// implements the methods needed to operate as a NeoPixelBus method.
template<typename T_SPEED, typename T_BASE, typename T_INVERT>
class NeoEsp8266UartMethodBase: public T_BASE
{
public:
NeoEsp8266UartMethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize)
: T_BASE(pixelCount, elementSize, settingsSize)
{
}
NeoEsp8266UartMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize)
: T_BASE(pixelCount, elementSize, settingsSize)
{
}
bool IsReadyToUpdate() const
{
uint32_t delta = micros() - this->_startTime;
return delta >= getPixelTime() + T_SPEED::ResetTimeUs;
}
void Initialize()
{
this->InitializeUart(T_SPEED::UartBaud, T_INVERT::Inverted);
// Inverting logic levels can generate a phantom bit in the led strip bus
// We need to delay 50+ microseconds the output stream to force a data
// latch and discard this bit. Otherwise, that bit would be prepended to
// the first frame corrupting it.
this->_startTime = micros() - getPixelTime();
}
void Update(bool maintainBufferConsistency)
{
// Data latch = 50+ microsecond pause in the output stream. Rather than
// put a delay at the end of the function, the ending time is noted and
// the function will simply hold off (if needed) on issuing the
// subsequent round of data until the latch time has elapsed. This
// allows the mainline code to start generating the next frame of data
// rather than stalling for the latch.
while (!this->IsReadyToUpdate())
{
yield();
}
this->UpdateUart(maintainBufferConsistency);
}
uint8_t* getData() const
{
return this->_data;
};
size_t getDataSize() const
{
return this->_sizeData;
};
private:
uint32_t getPixelTime() const
{
return (T_SPEED::ByteSendTimeUs * this->_sizeData);
};
};
// uart 0
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedTm1814, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0Tm1814Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0400KbpsMethod;
typedef NeoEsp8266Uart0Ws2812xMethod NeoEsp8266Uart0Ws2813Method;
typedef NeoEsp8266Uart0800KbpsMethod NeoEsp8266Uart0Ws2812Method;
typedef NeoEsp8266Uart0Ws2812xMethod NeoEsp8266Uart0Ws2811Method;
typedef NeoEsp8266Uart0Sk6812Method NeoEsp8266Uart0Lc8812Method;
// uart 1
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedTm1814, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1Tm1814Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1400KbpsMethod;
typedef NeoEsp8266Uart1Ws2812xMethod NeoEsp8266Uart1Ws2813Method;
typedef NeoEsp8266Uart1800KbpsMethod NeoEsp8266Uart1Ws2812Method;
typedef NeoEsp8266Uart1Ws2812xMethod NeoEsp8266Uart1Ws2811Method;
typedef NeoEsp8266Uart1Sk6812Method NeoEsp8266Uart1Lc8812Method;
// uart 0 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedTm1814, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0Tm1814Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0400KbpsMethod;
typedef NeoEsp8266AsyncUart0Ws2812xMethod NeoEsp8266AsyncUart0Ws2813Method;
typedef NeoEsp8266AsyncUart0800KbpsMethod NeoEsp8266AsyncUart0Ws2812Method;
typedef NeoEsp8266AsyncUart0Ws2812xMethod NeoEsp8266AsyncUart0Ws2811Method;
typedef NeoEsp8266AsyncUart0Sk6812Method NeoEsp8266AsyncUart0Lc8812Method;
// uart 1 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedTm1814, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1Tm1814Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1400KbpsMethod;
typedef NeoEsp8266AsyncUart1Ws2812xMethod NeoEsp8266AsyncUart1Ws2813Method;
typedef NeoEsp8266AsyncUart1800KbpsMethod NeoEsp8266AsyncUart1Ws2812Method;
typedef NeoEsp8266AsyncUart1Ws2812xMethod NeoEsp8266AsyncUart1Ws2811Method;
typedef NeoEsp8266AsyncUart1Sk6812Method NeoEsp8266AsyncUart1Lc8812Method;
// inverted
//
// uart 0
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0Ws2812xInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0Sk6812InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedTm1814, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0Tm1814InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0Apa106InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0800KbpsInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0400KbpsInvertedMethod;
typedef NeoEsp8266Uart0Ws2812xInvertedMethod NeoEsp8266Uart0Ws2813InvertedMethod;
typedef NeoEsp8266Uart0800KbpsInvertedMethod NeoEsp8266Uart0Ws2812InvertedMethod;
typedef NeoEsp8266Uart0Ws2812xInvertedMethod NeoEsp8266Uart0Ws2811InvertedMethod;
typedef NeoEsp8266Uart0Sk6812InvertedMethod NeoEsp8266Uart0Lc8812InvertedMethod;
// uart 1
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1Ws2812xInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1Sk6812InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedTm1814, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1Tm1814InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1Apa106InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1800KbpsInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1400KbpsInvertedMethod;
typedef NeoEsp8266Uart1Ws2812xInvertedMethod NeoEsp8266Uart1Ws2813InvertedMethod;
typedef NeoEsp8266Uart1800KbpsInvertedMethod NeoEsp8266Uart1Ws2812InvertedMethod;
typedef NeoEsp8266Uart1Ws2812xInvertedMethod NeoEsp8266Uart1Ws2811InvertedMethod;
typedef NeoEsp8266Uart1Sk6812InvertedMethod NeoEsp8266Uart1Lc8812InvertedMethod;
// uart 0 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0Ws2812xInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0Sk6812InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedTm1814, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0Tm1814InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0Apa106InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0800KbpsInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0400KbpsInvertedMethod;
typedef NeoEsp8266AsyncUart0Ws2812xInvertedMethod NeoEsp8266AsyncUart0Ws2813InvertedMethod;
typedef NeoEsp8266AsyncUart0800KbpsInvertedMethod NeoEsp8266AsyncUart0Ws2812InvertedMethod;
typedef NeoEsp8266AsyncUart0Ws2812xInvertedMethod NeoEsp8266AsyncUart0Ws2811InvertedMethod;
typedef NeoEsp8266AsyncUart0Sk6812InvertedMethod NeoEsp8266AsyncUart0Lc8812InvertedMethod;
// uart 1 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1Ws2812xInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1Sk6812InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedTm1814, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1Tm1814InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1Apa106InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1800KbpsInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1400KbpsInvertedMethod;
typedef NeoEsp8266AsyncUart1Ws2812xInvertedMethod NeoEsp8266AsyncUart1Ws2813InvertedMethod;
typedef NeoEsp8266AsyncUart1800KbpsInvertedMethod NeoEsp8266AsyncUart1Ws2812InvertedMethod;
typedef NeoEsp8266AsyncUart1Ws2812xInvertedMethod NeoEsp8266AsyncUart1Ws2811InvertedMethod;
typedef NeoEsp8266AsyncUart1Sk6812InvertedMethod NeoEsp8266AsyncUart1Lc8812InvertedMethod;
#endif

View File

@ -0,0 +1,401 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp8266 and Esp32
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
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#if defined(ARDUINO_ARCH_ESP8266)
#include <eagle_soc.h>
#endif
// ESP32 doesn't define ICACHE_RAM_ATTR
#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR IRAM_ATTR
#endif
#define CYCLES_LOOPTEST (4) // adjustment due to loop exit test instruction cycles
class NeoEspSpeedWs2811
{
public:
const static uint32_t T0H = (F_CPU / 3333333 - CYCLES_LOOPTEST); // 0.3us
const static uint32_t T1H = (F_CPU / 1052632 - CYCLES_LOOPTEST); // 0.95us
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
};
class NeoEspSpeedTm1814
{
public:
const static uint32_t T0H = (F_CPU / 2916666 - CYCLES_LOOPTEST); // 0.35us
const static uint32_t T1H = (F_CPU / 1666666 - CYCLES_LOOPTEST); // 0.75us
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
};
class NeoEspSpeed800Mhz
{
public:
const static uint32_t T0H = (F_CPU / 2500000 - CYCLES_LOOPTEST); // 0.4us
const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
};
class NeoEspSpeed400Mhz
{
public:
const static uint32_t T0H = (F_CPU / 2000000 - CYCLES_LOOPTEST);
const static uint32_t T1H = (F_CPU / 833333 - CYCLES_LOOPTEST);
const static uint32_t Period = (F_CPU / 400000 - CYCLES_LOOPTEST);
};
class NeoEspPinset
{
public:
const static uint8_t IdleLevel = LOW;
inline static void setPin(const uint32_t pinRegister)
{
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
#endif
}
inline static void resetPin(const uint32_t pinRegister)
{
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1tc = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
#endif
}
};
class NeoEspPinsetInverted
{
public:
const static uint8_t IdleLevel = HIGH;
inline static void setPin(const uint32_t pinRegister)
{
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1tc = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
#endif
}
inline static void resetPin(const uint32_t pinRegister)
{
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
#endif
}
};
template<typename T_SPEED, typename T_PINSET> class NeoEspBitBangBase
{
public:
__attribute__((noinline)) static void ICACHE_RAM_ATTR send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
const uint32_t pinRegister = _BV(pin);
uint8_t mask = 0x80;
uint8_t subpix = *pixels++;
uint32_t cyclesStart = 0; // trigger emediately
uint32_t cyclesNext = 0;
for (;;)
{
// do the checks here while we are waiting on time to pass
uint32_t cyclesBit = T_SPEED::T0H;
if (subpix & mask)
{
cyclesBit = T_SPEED::T1H;
}
// after we have done as much work as needed for this next bit
// now wait for the HIGH
while (((cyclesStart = getCycleCount()) - cyclesNext) < T_SPEED::Period);
// set pin state
T_PINSET::setPin(pinRegister);
// wait for the LOW
while ((getCycleCount() - cyclesStart) < cyclesBit);
// reset pin start
T_PINSET::resetPin(pinRegister);
cyclesNext = cyclesStart;
// next bit
mask >>= 1;
if (mask == 0)
{
// no more bits to send in this byte
// check for another byte
if (pixels >= end)
{
// no more bytes to send so stop
break;
}
// reset mask to first bit and get the next byte
mask = 0x80;
subpix = *pixels++;
}
}
}
protected:
static inline uint32_t getCycleCount(void)
{
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
return ccount;
}
};
class NeoEspBitBangSpeedWs2811 : public NeoEspBitBangBase<NeoEspSpeedWs2811, NeoEspPinset>
{
public:
static const uint32_t ResetTimeUs = 300;
};
class NeoEspBitBangSpeedWs2812x : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinset>
{
public:
static const uint32_t ResetTimeUs = 300;
};
class NeoEspBitBangSpeedSk6812 : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinset>
{
public:
static const uint32_t ResetTimeUs = 80;
};
// normal is inverted signal
class NeoEspBitBangSpeedTm1814 : public NeoEspBitBangBase<NeoEspSpeedTm1814, NeoEspPinsetInverted>
{
public:
static const uint32_t ResetTimeUs = 200;
};
class NeoEspBitBangSpeed800Kbps : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinset>
{
public:
static const uint32_t ResetTimeUs = 50;
};
class NeoEspBitBangSpeed400Kbps : public NeoEspBitBangBase<NeoEspSpeed400Mhz, NeoEspPinset>
{
public:
static const uint32_t ResetTimeUs = 50;
};
class NeoEspBitBangInvertedSpeedWs2811 : public NeoEspBitBangBase<NeoEspSpeedWs2811, NeoEspPinsetInverted>
{
public:
static const uint32_t ResetTimeUs = 300;
};
class NeoEspBitBangInvertedSpeedWs2812x : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinsetInverted>
{
public:
static const uint32_t ResetTimeUs = 300;
};
class NeoEspBitBangInvertedSpeedSk6812 : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinsetInverted>
{
public:
static const uint32_t ResetTimeUs = 80;
};
// normal is inverted signal, so inverted is normal
class NeoEspBitBangInvertedSpeedTm1814 : public NeoEspBitBangBase<NeoEspSpeedTm1814, NeoEspPinset>
{
public:
static const uint32_t ResetTimeUs = 200;
};
class NeoEspBitBangInvertedSpeed800Kbps : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinsetInverted>
{
public:
static const uint32_t ResetTimeUs = 50;
};
class NeoEspBitBangInvertedSpeed400Kbps : public NeoEspBitBangBase<NeoEspSpeed400Mhz, NeoEspPinsetInverted>
{
public:
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEED, typename T_PINSET> class NeoEspBitBangMethodBase
{
public:
NeoEspBitBangMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize),
_pin(pin)
{
pinMode(pin, OUTPUT);
_data = static_cast<uint8_t*>(malloc(_sizeData));
memset(_data, 0, _sizeData);
}
~NeoEspBitBangMethodBase()
{
pinMode(_pin, INPUT);
free(_data);
}
bool IsReadyToUpdate() const
{
uint32_t delta = micros() - _endTime;
return (delta >= T_SPEED::ResetTimeUs);
}
void Initialize()
{
digitalWrite(_pin, T_PINSET::IdleLevel);
_endTime = micros();
}
void Update(bool)
{
// Data latch = 50+ microsecond pause in the output stream. Rather than
// put a delay at the end of the function, the ending time is noted and
// the function will simply hold off (if needed) on issuing the
// subsequent round of data until the latch time has elapsed. This
// allows the mainline code to start generating the next frame of data
// rather than stalling for the latch.
while (!IsReadyToUpdate())
{
yield(); // allows for system yield if needed
}
// Need 100% focus on instruction timing
#if defined(ARDUINO_ARCH_ESP32)
delay(1); // required
portMUX_TYPE updateMux = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&updateMux);
#else
noInterrupts();
#endif
T_SPEED::send_pixels(_data, _data + _sizeData, _pin);
#if defined(ARDUINO_ARCH_ESP32)
portEXIT_CRITICAL(&updateMux);
#else
interrupts();
#endif
// save EOD time for latch on next call
_endTime = micros();
}
uint8_t* getData() const
{
return _data;
};
size_t getDataSize() const
{
return _sizeData;
};
private:
const size_t _sizeData; // Size of '_data' buffer below
const uint8_t _pin; // output pin number
uint32_t _endTime; // Latch timing reference
uint8_t* _data; // Holds LED color values
};
#if defined(ARDUINO_ARCH_ESP32)
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2811, NeoEspPinset> NeoEsp32BitBangWs2811Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x, NeoEspPinset> NeoEsp32BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812, NeoEspPinset> NeoEsp32BitBangSk6812Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedTm1814, NeoEspPinsetInverted> NeoEsp32BitBangTm1814Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps, NeoEspPinset> NeoEsp32BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps, NeoEspPinset> NeoEsp32BitBang400KbpsMethod;
typedef NeoEsp32BitBangWs2812xMethod NeoEsp32BitBangWs2813Method;
typedef NeoEsp32BitBang800KbpsMethod NeoEsp32BitBangWs2812Method;
typedef NeoEsp32BitBangSk6812Method NeoEsp32BitBangLc8812Method;
typedef NeoEsp32BitBang400KbpsMethod NeoEsp32BitBangApa106Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2811, NeoEspPinsetInverted> NeoEsp32BitBangWs2811InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2812x, NeoEspPinsetInverted> NeoEsp32BitBangWs2812xInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedSk6812, NeoEspPinsetInverted> NeoEsp32BitBangSk6812InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedTm1814, NeoEspPinset> NeoEsp32BitBangTm1814InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed800Kbps, NeoEspPinsetInverted> NeoEsp32BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed400Kbps, NeoEspPinsetInverted> NeoEsp32BitBang400KbpsInvertedMethod;
typedef NeoEsp32BitBangWs2812xInvertedMethod NeoEsp32BitBangWs2813InvertedMethod;
typedef NeoEsp32BitBang800KbpsInvertedMethod NeoEsp32BitBangWs2812InvertedMethod;
typedef NeoEsp32BitBangSk6812InvertedMethod NeoEsp32BitBangLc8812InvertedMethod;
typedef NeoEsp32BitBang400KbpsInvertedMethod NeoEsp32BitBangApa106InvertedMethod;
#else
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2811, NeoEspPinset> NeoEsp8266BitBangWs2811Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x, NeoEspPinset> NeoEsp8266BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812, NeoEspPinset> NeoEsp8266BitBangSk6812Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedTm1814, NeoEspPinsetInverted> NeoEsp8266BitBangTm1814Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps, NeoEspPinset> NeoEsp8266BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps, NeoEspPinset> NeoEsp8266BitBang400KbpsMethod;
typedef NeoEsp8266BitBangWs2812xMethod NeoEsp8266BitBangWs2813Method;
typedef NeoEsp8266BitBang800KbpsMethod NeoEsp8266BitBangWs2812Method;
typedef NeoEsp8266BitBangSk6812Method NeoEsp8266BitBangLc8812Method;
typedef NeoEsp8266BitBang400KbpsMethod NeoEsp8266BitBangApa106Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2811, NeoEspPinsetInverted> NeoEsp8266BitBangWs2811InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2812x, NeoEspPinsetInverted> NeoEsp8266BitBangWs2812xInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedSk6812, NeoEspPinsetInverted> NeoEsp8266BitBangSk6812InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedTm1814, NeoEspPinset> NeoEsp8266BitBangTm1814InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed800Kbps, NeoEspPinsetInverted> NeoEsp8266BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed400Kbps, NeoEspPinsetInverted> NeoEsp8266BitBang400KbpsInvertedMethod;
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
#endif

View File

@ -25,10 +25,7 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#include <Arduino.h>
#include "RgbColor.h"
#include "RgbwColor.h"
#include "NeoEase.h"
#include "NeoGamma.h"
#include "NeoPixelBus.h"
const uint8_t NeoGammaTableMethod::_table[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

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