├── .github
├── dependabot.yml
└── workflows
│ ├── esp-idf-with-gfx.yml
│ ├── esp-idf-without-gfx.yml
│ └── pio_arduino_build.yml
├── CMakeLists.txt
├── Kconfig.projbuild
├── LICENSE.txt
├── README.md
├── component.mk
├── doc
├── BuildOptions.md
├── Panel_Chaining_Types.ods
├── ScanRateGraphic.jpg
├── ScanRateGraphic.odp
├── VirtualMatrixPanel.odp
├── VirtualMatrixPanel.pdf
├── fillrate.md
├── memcalc.jpg
├── memcalc.md
└── memcalc.xlsm
├── examples
├── 1_SimpleTestShapes
│ └── 1_SimpleTestShapes.ino
├── 2_PatternPlasma
│ ├── 2_PatternPlasma.ino
│ ├── PatternWave.jpg
│ └── README.md
├── 3_DoubleBuffer
│ └── 3_DoubleBuffer.ino
├── 4_OtherShiftDriverPanel
│ ├── 4_OtherShiftDriverPanel.ino
│ ├── FM6126A.md
│ └── README.md
├── AnimatedGIFPanel_LittleFS
│ ├── AnimatedGIFPanel_LittleFS.ino
│ ├── README.md
│ └── data
│ │ └── gifs
│ │ ├── cartoon.gif
│ │ ├── ezgif.com-pacmn.gif
│ │ ├── loading.io-64x32px.gif
│ │ ├── matrix-spin.gif
│ │ ├── parasite1.gif
│ │ ├── parasite2.gif
│ │ └── shock-gs.gif
├── AnimatedGIFPanel_SD
│ ├── AnimatedGIFPanel_SD.ino
│ ├── Readme.md
│ ├── esp32_sdcard.jpg
│ ├── gif_functions.hpp
│ ├── gifs
│ │ ├── cartoon.gif
│ │ ├── ezgif.com-pacmn.gif
│ │ ├── loading.io-64x32px.gif
│ │ ├── matrix-spin.gif
│ │ ├── parasite1.gif
│ │ ├── parasite2.gif
│ │ └── shock-gs.gif
│ └── sdcard_functions.hpp
├── AuroraDemo
│ ├── Attractor.hpp
│ ├── AuroraDemo.ino
│ ├── Boid.hpp
│ ├── Drawable.hpp
│ ├── EffectsLayer.hpp
│ ├── Geometry.hpp
│ ├── PatternAttract.hpp
│ ├── PatternBounce.hpp
│ ├── PatternCube.hpp
│ ├── PatternElectricMandala.hpp
│ ├── PatternFireKoz.hpp
│ ├── PatternFireworks.hpp
│ ├── PatternFlock.hpp
│ ├── PatternFlowField.hpp
│ ├── PatternGreenScroll.hpp
│ ├── PatternIncrementalDrift.hpp
│ ├── PatternIncrementalDrift2.hpp
│ ├── PatternInfinity.hpp
│ ├── PatternJuliaSetFractal.hpp
│ ├── PatternMaze.hpp
│ ├── PatternMunch.hpp
│ ├── PatternNoiseSmearing.hpp
│ ├── PatternPendulumWave.hpp
│ ├── PatternPlasma.hpp
│ ├── PatternRadar.hpp
│ ├── PatternRain.hpp
│ ├── PatternSimplexNoise.hpp
│ ├── PatternSnake.hpp
│ ├── PatternSpin.hpp
│ ├── PatternSpiral.hpp
│ ├── PatternSpiro.hpp
│ ├── PatternStarfield.hpp
│ ├── PatternTest.hpp
│ ├── PatternWave.hpp
│ ├── Patterns.hpp
│ ├── README.md
│ └── Vector2.hpp
├── BitmapIcons
│ ├── BitmapIcons.ino
│ ├── Dhole_weather_icons32px.h
│ ├── README.md
│ ├── WiFi1bit.bmp
│ ├── bmp2hex.py
│ └── screenshot.jpg
├── HueValueSpectrum
│ └── HueValueSpectrum.ino
├── PIO_TestPatterns
│ ├── README.md
│ ├── platformio.ini
│ ├── sdkconfig.defaults
│ └── src
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ └── main.h
├── Pixel_Mapping_Test
│ ├── Pixel_Mapping_Test.ino
│ └── README.md
├── README.md
├── ScrollingTextLayer
│ └── ScrollingTextLayer.ino
├── VirtualMatrixPanel
│ ├── README.md
│ └── VirtualMatrixPanel.ino
└── esp-idf
│ ├── .gitignore
│ ├── with-gfx
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── components
│ │ └── .gitignore
│ ├── main
│ │ ├── CMakeLists.txt
│ │ └── main.cpp
│ └── sdkconfig.defaults
│ └── without-gfx
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── components
│ └── .gitignore
│ ├── main
│ ├── CMakeLists.txt
│ └── main.cpp
│ └── sdkconfig.defaults
├── image.jpg
├── keywords.txt
├── library.json
├── library.properties
├── src
├── ESP32-HUB75-MatrixPanel-I2S-DMA.cpp
├── ESP32-HUB75-MatrixPanel-I2S-DMA.h
├── ESP32-HUB75-MatrixPanel-leddrivers.cpp
├── ESP32-HUB75-VirtualMatrixPanel_T.hpp
├── ESP32-VirtualMatrixPanel-I2S-DMA.h
└── platforms
│ ├── esp32
│ ├── RGB_HUB75_PINS.png
│ ├── esp32-default-pins.hpp
│ ├── esp32_i2s_parallel_dma.cpp
│ └── esp32_i2s_parallel_dma.hpp
│ ├── esp32c6
│ ├── dma_parallel_io.cpp.notused
│ ├── dma_parallel_io.hpp.notused
│ └── esp32c6-default-pins.hpp.notused
│ ├── esp32s2
│ └── esp32s2-default-pins.hpp
│ ├── esp32s3
│ ├── ESP32-S3-DevKitC-1-pin-layout.png
│ ├── Readme.md
│ ├── ReservedPinsForPSRAM.PNG
│ ├── esp32s3-default-pins.hpp
│ ├── gdma_lcd_parallel16.cpp
│ └── gdma_lcd_parallel16.hpp
│ └── platform_detect.hpp
└── testing
├── README.md
├── baseline.hpp
├── four_scan_40_80px_hfarcan.cpp
└── virtual.cpp
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "github-actions" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "weekly"
12 |
--------------------------------------------------------------------------------
/.github/workflows/esp-idf-with-gfx.yml:
--------------------------------------------------------------------------------
1 | name: esp-idf with Adafruit GFX Library
2 |
3 | on:
4 | push:
5 | paths-ignore:
6 | - '**.md'
7 | - 'doc/**'
8 | pull_request:
9 | paths-ignore:
10 | - '**.md'
11 | - 'doc/**'
12 |
13 | jobs:
14 | build:
15 | name: esp-idf v5.3.2 with Adafruit GFX
16 |
17 | runs-on: ubuntu-latest
18 |
19 | steps:
20 | - name: Checkout repo
21 | uses: actions/checkout@v4
22 | with:
23 | submodules: 'recursive'
24 | - name: Checkout ESP32-HUB75-MatrixPanel-I2S-DMA component
25 | uses: actions/checkout@v4
26 | with:
27 | path: 'examples/esp-idf/with-gfx/components/ESP32-HUB75-MatrixPanel-I2S-DMA'
28 | - name: Checkout Adafruit-GFX-Library repo
29 | uses: actions/checkout@v4
30 | with:
31 | repository: 'adafruit/Adafruit-GFX-Library'
32 | path: 'examples/esp-idf/with-gfx/components/Adafruit-GFX-Library'
33 | - name: Checkout Adafruit_BusIO repo
34 | uses: actions/checkout@v4
35 | with:
36 | repository: 'adafruit/Adafruit_BusIO'
37 | path: 'examples/esp-idf/with-gfx/components/Adafruit_BusIO'
38 | - name: Checkout arduino-esp32 repo
39 | uses: actions/checkout@v4
40 | with:
41 | repository: 'espressif/arduino-esp32'
42 | ref: 3.1.3
43 | path: 'examples/esp-idf/with-gfx/components/arduino'
44 | - name: Edit Adafruit_BusIO CMakeLists.txt
45 | run: sed -i 's/arduino-esp32)/arduino)/g' examples/esp-idf/with-gfx/components/Adafruit_BusIO/CMakeLists.txt
46 | - name: esp-idf build
47 | uses: espressif/esp-idf-ci-action@v1
48 | with:
49 | esp_idf_version: v5.3.2
50 | target: esp32
51 | path: 'examples/esp-idf/with-gfx'
52 |
--------------------------------------------------------------------------------
/.github/workflows/esp-idf-without-gfx.yml:
--------------------------------------------------------------------------------
1 | name: esp-idf without Adafruit GFX Library
2 |
3 | on:
4 | push:
5 | paths-ignore:
6 | - '**.md'
7 | - 'doc/**'
8 | pull_request:
9 | paths-ignore:
10 | - '**.md'
11 | - 'doc/**'
12 |
13 | jobs:
14 | build:
15 | name: esp-idf 5.1.4 without Adafruit GFX
16 |
17 | runs-on: ubuntu-latest
18 |
19 | steps:
20 | - name: Checkout repo
21 | uses: actions/checkout@v4
22 | with:
23 | submodules: 'recursive'
24 | - name: Checkout ESP32-HUB75-MatrixPanel-I2S-DMA component
25 | uses: actions/checkout@v4
26 | with:
27 | path: 'examples/esp-idf/without-gfx/components/ESP32-HUB75-MatrixPanel-I2S-DMA'
28 | - name: esp-idf build
29 | uses: espressif/esp-idf-ci-action@v1
30 | with:
31 | esp_idf_version: v5.1.4
32 | target: esp32
33 | path: 'examples/esp-idf/without-gfx'
34 |
--------------------------------------------------------------------------------
/.github/workflows/pio_arduino_build.yml:
--------------------------------------------------------------------------------
1 | # Build examples with Platformio
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3 | # https://docs.platformio.org/en/latest/integration/ci/github-actions.html
4 |
5 | name: PlatformIO 6.1.17 Arduino CI
6 |
7 | on:
8 | push:
9 | branches: [ master, dev ]
10 | paths-ignore:
11 | - '**.md'
12 | - 'doc/**'
13 | pull_request:
14 | branches: [ master, dev ]
15 | paths-ignore:
16 | - '**.md'
17 | - 'doc/**'
18 |
19 | jobs:
20 | build:
21 |
22 | runs-on: ubuntu-latest
23 | strategy:
24 | matrix:
25 | framework: ["Arduino", "IDF"]
26 | no_gfx: ["", -DNO_GFX]
27 | # no_fast_functions: ["", -DNO_FAST_FUNCTIONS]
28 | # no_cie1931: ["", -DNO_CIE1931]
29 | # virtual_panel: ["", -DVIRTUAL_PANE]
30 | example:
31 | - "examples/PIO_TestPatterns"
32 | # exclude:
33 | # - no_fast_functions: ""
34 | # virtual_panel: -DVIRTUAL_PANE
35 |
36 | steps:
37 | - name: Checkout
38 | uses: actions/checkout@v4
39 | - name: Cache pip and platformio
40 | uses: actions/cache@v4
41 | with:
42 | path: |
43 | ~/.cache/pip
44 | ~/.platformio/.cache
45 | key: ${{ runner.os }}-pio
46 | - name: Set up Python 3.x
47 | uses: actions/setup-python@v5
48 | with:
49 | python-version: '3.x'
50 | - name: Install Platformio
51 | run: pip install --upgrade platformio==6.1.17
52 | - name: Run PlatformIO CI (Arduino)
53 | if: ${{ matrix.framework == 'Arduino'}}
54 | env:
55 | PLATFORMIO_BUILD_FLAGS: ${{ matrix.no_gfx }} ${{ matrix.no_fast_functions }} ${{ matrix.no_cie1931 }} ${{ matrix.virtual_panel }}
56 | PLATFORMIO_CI_SRC: ${{ matrix.example }}
57 | run: pio ci -e esp32 -c ${{ matrix.example }}/platformio.ini
58 | - name: Run PlatformIO CI (ESP-IDF)
59 | if: ${{ matrix.framework == 'IDF'}}
60 | env:
61 | PLATFORMIO_BUILD_FLAGS: -DIDF_BUILD ${{ matrix.no_gfx }} ${{ matrix.no_fast_functions }} ${{ matrix.no_cie1931 }} ${{ matrix.virtual_panel }}
62 | # pio ci doesn't use our sdkconfig, so we have to use pio run
63 | #run: pio run -d ${{ matrix.example }} -e esp32idf -c ${{ matrix.example }}/platformio.ini
64 | run: pio run -d ${{ matrix.example }}
65 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # HUB75 RGB LED matrix library utilizing ESP32 DMA Engine
2 | # https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA
3 | # MIT License
4 |
5 | cmake_minimum_required(VERSION 3.5)
6 | idf_build_get_property(target IDF_TARGET)
7 |
8 | if(ARDUINO_ARCH_ESP32 OR CONFIG_ESP32_HUB75_USE_GFX)
9 | list(APPEND build_dependencies arduino Adafruit-GFX-Library)
10 | else()
11 | list(APPEND build_dependencies esp_lcd driver)
12 | endif()
13 |
14 | if(${target} STREQUAL "esp32s3")
15 | list(APPEND extra_srcs src/platforms/${target}/gdma_lcd_parallel16.cpp)
16 |
17 | # Required by gdma_lcd_parallel16.cpp
18 | if (NOT esp_lcd IN_LIST build_dependencies)
19 | list(APPEND build_dependencies esp_lcd)
20 | endif()
21 | endif()
22 |
23 | idf_component_register(SRCS "src/platforms/esp32/esp32_i2s_parallel_dma.cpp" "src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp" "src/ESP32-HUB75-MatrixPanel-leddrivers.cpp" ${extra_srcs}
24 | INCLUDE_DIRS "./src"
25 | )
26 |
27 | # Dependencies cannot be added to the REQUIRES argument of `idf_component_register` because (according to the build process
28 | # listed at https://docs.espressif.com/projects/esp-idf/en/v4.2/esp32/api-guides/build-system.html#build-process)
29 | # `idf_component_register` is processed during the "Enumeration" stage which happens before the sdkconfig file is loaded
30 | # in the "Processing" stage. So if dependencies are going to be loaded based on certain CONFIG_* variables we must
31 | # use `target_link_libraries` instead. This is the method used by Arduino's CMakeLists.txt file.
32 | idf_build_get_property(components BUILD_COMPONENTS)
33 | foreach(component_name IN LISTS build_dependencies)
34 | if (NOT ${component_name} IN_LIST components)
35 | message(FATAL_ERROR "Missing component: ${component_name}")
36 | endif()
37 | idf_component_get_property(lib_name ${component_name} COMPONENT_LIB)
38 | target_link_libraries(${COMPONENT_LIB} PUBLIC ${lib_name})
39 | endforeach()
40 |
41 | # In case you are running into issues with "missing" header files from 3rd party libraries
42 | # you can add them to the REQUIRES section above. If you use some of the build options below
43 | # you probably want to remove (NO_GFX) or replace Adafruit-GFX-Library (USE_GFX_ROOT)
44 |
45 | # Example to build with USE_GFX_ROOT or NO_GFX / just uncomment the appropriate line
46 | # target_compile_options(${COMPONENT_TARGET} PUBLIC -DUSE_GFX_ROOT)
47 | # target_compile_options(${COMPONENT_TARGET} PUBLIC -DNO_GFX)
48 |
49 | # esp-idf does not have any GFX library support yet, so we need to define NO_GFX
50 | if(ARDUINO_ARCH_ESP32 OR CONFIG_ESP32_HUB75_USE_GFX)
51 | else()
52 | target_compile_options(${COMPONENT_TARGET} PUBLIC -DNO_GFX)
53 | if(${target} STREQUAL "esp32s3")
54 | # Don't enable PSRAM based framebuffer just because it's an S3.
55 | # This is an advanced option and should only be used with an S3 with Octal-SPI RAM.
56 | # target_compile_options(${COMPONENT_TARGET} PUBLIC -DSPIRAM_FRAMEBUFFER)
57 | target_compile_options(${COMPONENT_TARGET} PUBLIC)
58 | endif()
59 | endif()
60 |
61 | # You can also use multiple options like this
62 | # target_compile_options(${COMPONENT_TARGET} PUBLIC -DNO_GFX -DNO_FAST_FUNCTIONS)
63 |
64 | # All options can be found here:
65 | # https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/blob/master/doc/BuildOptions.md
66 |
67 | project(ESP32-HUB75-MatrixPanel-I2S-DMA)
68 |
--------------------------------------------------------------------------------
/Kconfig.projbuild:
--------------------------------------------------------------------------------
1 | menu "ESP32 HUB75 Configuration"
2 |
3 | config ESP32_HUB75_USE_GFX
4 | bool "Use Adafruit GFX library."
5 | default y
6 | help
7 | This option enables use of the Adafruit GFX library using the `Adafruit-GFX-Library` component.
8 |
9 | endmenu
10 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2032 Faptastic
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/component.mk:
--------------------------------------------------------------------------------
1 | COMPONENT_ADD_INCLUDEDIRS = .
2 |
--------------------------------------------------------------------------------
/doc/BuildOptions.md:
--------------------------------------------------------------------------------
1 | ### Build Options and flags
2 |
3 | This library supports build-time defines to modify its features or enable greater debugging information. Please use the debugging capabilities before raising any issues.
4 |
5 | For example build flags could be set using PlatformIO's .ini file like this
6 |
7 | ```
8 | [env]
9 | framework = arduino
10 | platform = espressif32
11 | lib_deps =
12 | ESP32 HUB75 LED MATRIX PANEL DMA Display
13 | build_flags =
14 | -DCORE_DEBUG_LEVEL=3
15 | -DNO_GFX=1
16 | (etc.....)
17 | ```
18 | Or if using Arduino: 'Tools' menu > 'Core Debug Level' > Select 'Debug'
19 |
20 | ... and use the Serial output to see the debug information.
21 |
22 | ## Build flags
23 |
24 | | Flag | Description | Note |
25 | | :------------ |---------------|-----|
26 | | **CORE_DEBUG_LEVEL** |Adjust the espressif ESP32 IDF debug level, for which this library leverages to output information on what is going on when allocating memory etc. This will provide detailed information about memory allocations, DMA descriptors setup and color depth [BCM](http://www.batsocks.co.uk/readme/art_bcm_5.htm) |Set value to at least 3 [(Info)](https://iotespresso.com/core-debug-level-in-esp32/)
27 | | **USE_GFX_ROOT** | Use [lightweight](https://github.com/mrfaptastic/Adafruit_GFX_Lite) version of AdafuitGFX, without Adafruit BusIO extensions | You **must** install [Adafruit_GFX_Lite](https://github.com/mrfaptastic/Adafruit_GFX_Lite) library instead of original AdafruitGFX|
28 | | **NO_GFX** | Build without AdafuitGFX API, only native methods supported based on manipulating DMA buffer. I.e. no methods of drawing circles/shapes, typing text or using fonts!!! This might save some resources for applications using it's own internal graphics buffer or working solely with per-pixel manipulation. | Use this if you rely on FastLED, Neomatrix or any other API. For example [Aurora](/examples/AuroraDemo/) effects can work fine w/o AdafruitGFX. |
29 | | **NO_FAST_FUNCTIONS** | Do not build auxiliary speed-optimized functions. Those are used to speed-up operations like drawing straight lines or rectangles. Otherwise lines/shapes are drawn using drawPixel() method. The trade-off for speed is RAM/code-size, take it or leave it ;) | If you are not using AdafruitGFX than you probably do not need this either|
30 | |**NO_CIE1931**|Do not use LED brightness [compensation](https://ledshield.wordpress.com/2012/11/13/led-brightness-to-your-eye-gamma-correction-no/) described in [CIE 1931](https://en.wikipedia.org/wiki/CIE_1931_color_space). Normally library would adjust every pixel's RGB888 so that luminance (or brightness control) for the corresponding LED's would appear 'linear' to the human's eye. I.e. a white dot with rgb(128,128,128) would seem to be at 50% brightness between rgb(0,0,0) and rgb(255,255,255). Normally you would like to keep this enabled by default. Not only it makes brightness control "linear", it also makes colours more vivid, otherwise it looks brighter but 'bleached'.|You might want to turn it off in some special cases like:
- Using some other overlay lib for intermediate calculations that makes it's own compensation, like FastLED's [dimming functions](http://fastled.io/docs/3.1/group___dimming.html).
- running at low colour depth's - it **might** (or might not) look better in shadows, darker gradients w/o compensation, try it
- you run for as bright output as possible, no matter what (make sure you have proper powering)
- you run for speed/save resources at all costs
|
31 | | **FORCE_COLOR_DEPTH** |In some cases the library may reduce colour fidelity to increase the refresh rate (i.e. reduce visible flicker). This is most likely to occur with a large chain of panels. However, if you want to force pure 24bpp colour, at the expense of likely noticeable flicker, then set this defined. |Not required in 99% of cases.
32 | | **SPIRAM_FRAMEBUFFER** |Use SPIRAM/PSRAM for the HUB75 DMA buffer and not internal SRAM. ONLY SUPPORTED ON ESP32-S3 VARIANTS WITH OCTAL (not quad!) SPIRAM/PSRAM, as ony OCTAL PSRAM an provide the required data rate / bandwidth to drive the panels adequately.|ONLY SUPPORTED ON ESP32-S3 VARIANTS WITH OCTAL (not quad) SPIRAM/PSRAM
33 |
34 | ## Build-time variables
35 |
36 | | Flag | Description | Note |
37 | | :------------ |---------------|-----|
38 | | **PIXEL_COLOR_DEPTH_BITS=8** | Colour depth per pixel in range 2-8. More bit's - more natural colour. But on the other hand every additional bit:- eats ~2.5 bits of DMA memory per pixel
- reduces matrix refresh rate in power of two due to nature of [BCM](http://www.batsocks.co.uk/readme/art_bcm_5.htm)
| For large chains of panels (i.e. 6 x 64x64 panels) you WILL need to reduce the colour depth, or likely run out of memory. Default is 8 bits per colour per pixel, i.e. True colour 24 bit RGB.
For higher resolutions, from 64x64 and above it is not possible to provide full 24 bits colour without significant flickering OR reducing dynamic range in shadows. In that case using 5-6 bits at high res make very small difference to the human’s eye actually. Refer to the [I2S memcalc](i2s_memcalc.md) for more details.
39 |
--------------------------------------------------------------------------------
/doc/Panel_Chaining_Types.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/doc/Panel_Chaining_Types.ods
--------------------------------------------------------------------------------
/doc/ScanRateGraphic.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/doc/ScanRateGraphic.jpg
--------------------------------------------------------------------------------
/doc/ScanRateGraphic.odp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/doc/ScanRateGraphic.odp
--------------------------------------------------------------------------------
/doc/VirtualMatrixPanel.odp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/doc/VirtualMatrixPanel.odp
--------------------------------------------------------------------------------
/doc/VirtualMatrixPanel.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/doc/VirtualMatrixPanel.pdf
--------------------------------------------------------------------------------
/doc/fillrate.md:
--------------------------------------------------------------------------------
1 | ## Estimating fillrate
2 |
3 | Here are some results of simple tests on filling DMA buffer with data.
4 | Filling DMA buffer requires lots of memory operations on a bit level rather than doing simple byte/word wide store and copy. And it looks like it's quite a task both for esp32 core and compiler.
5 | I've done this while optimizing loops and bit logic along with testing compiler results.
6 |
7 | So the testbed is:
8 | - Matrix modules: 4 x FM6126A based 64x64 modules chained in 256x64
9 |
10 | A testpatterns sketch:
11 | - allocating single DMA buffs for 256x64
12 | - allocating (NUM_LEDS*3) bytes for CRGB buffer
13 | - measuring microseconds for the following calls:
14 | - clearScreen() - full blanking
15 | - fillScreenRGB888() with monochrome/gray colors
16 | - fill screen using drawPixel()
17 | - filling some gradient into CRGB buff
18 | - painting CRGB buff into DMA buff with looped drawPixelRGB888()
19 | - drawing lines
20 |
21 |
22 | ||clearScreen()|drawPixelRGB888(), ticks|fillScreen()|fillScreen with a drawPixel()|fillRect() over Matrix|V-line with drawPixel|fast-V-line|H-line with drawPixel|fast-H-line|
23 | |--|--|--|--|--|--|--|--|--|--|
24 | |v1.2.4|1503113 ticks|9244 non-cached, 675 cached|1719 us, 412272 t|47149 us, 11315418 ticks|-|24505 us, 5880209 ticks|-|24200 us|-|
25 | |FastLines|1503113 ticks|1350 non-cached, 405 cached|1677 us, 401198 t|28511 us, 6841440 ticks|10395 us|14462 us, 3469605 ticks|10391 us, 2492743 ticks|14575 us|5180 us, 1242041 ticks|
26 |
27 | to be continued...
--------------------------------------------------------------------------------
/doc/memcalc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/doc/memcalc.jpg
--------------------------------------------------------------------------------
/doc/memcalc.md:
--------------------------------------------------------------------------------
1 | ### Memory Calculator
2 |
3 | I've made this [spreadsheet](memcalc.xlsm) to estimate all of the main parameters for ESP32-HUB75-MatrixPanel-DMA lib driving any combination of matrices/chains so that I do not need to reflash it hundreds of times just to check for the debug info about memory.
4 | Be sure to enable embedded macro's to allow refresh rate calculations.
5 |
6 | 
7 | Just fill-in all of the INPUT fields and get the OUTPUTs.
8 |
9 | So there are two main resources used to drive LED matrix
10 | - Memory
11 | - Bus clock speed (resulting in available bandwidth to pump pixel color data)
12 |
13 | And there are lot's of hogs for those:
14 | - matrix resolution (number of pixels)
15 | - number of modules in chain
16 | - pixel color depth
17 | - [BCM](http://www.batsocks.co.uk/readme/art_bcm_5.htm) LSB to MSB transition
18 | - double buffering
19 |
20 | Equalising ones with the others results in **Refresh rate**,
21 |
22 | or (rough approximation)
23 |
24 |
25 | [//]: # (github markdown does not like LaTex formulas)
26 | [//]: # ($$RefreshRate=\frac{resolution \times chain \times (ColorDepth-LSB2MSB)}{ I ^2S _ {clock} }$$)
27 |
28 | So, how to find optimum balance for all of these? Obviously you can't change *resolution* and *chain length*, it is physical characteristics and there is not much you can do about it except cutting off your chain or pushing it to the memory limits.
29 |
30 | There are 3 parameters you can choose from (actually two:)
31 | - **Color Depth** - predefined at [build-time](/doc/BuildOptions.md) option
32 |
33 | - I2S clock speed - run-time tunable with a very limited options
34 |
35 | - **LSB-to-MSB** transition - it can't be controlled in any way, library uses it internally trying to balance all of the above
36 |
37 | Using provided table it is possible to estimate all of the parameters before running the library. Besides calculating memory requirements it could help to find **optimum color depth** for your matrix configuration. For higher resolutions default 8 bits could be too much to sustain minimal refresh rate and avoid annoying flickering. So the library would increase MSB transition to keep the balance, thus reducing dynamic range in shadows and dark colors. As a result it is nearly almost the same as just reducing overall color depth. **But** reducing global color depth would also save lot's of precious RAM!
38 | Now it's all up to you to decide :)
39 |
40 | /Vortigont/
41 |
--------------------------------------------------------------------------------
/doc/memcalc.xlsm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/doc/memcalc.xlsm
--------------------------------------------------------------------------------
/examples/1_SimpleTestShapes/1_SimpleTestShapes.ino:
--------------------------------------------------------------------------------
1 |
2 | // Example sketch which shows how to display some patterns
3 | // on a 64x32 LED matrix
4 | //
5 |
6 | #include
7 |
8 |
9 | #define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
10 | #define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
11 | #define PANEL_CHAIN 1 // Total number of panels chained one to another
12 |
13 | //MatrixPanel_I2S_DMA dma_display;
14 | MatrixPanel_I2S_DMA *dma_display = nullptr;
15 |
16 | uint16_t myBLACK, myWHITE, myRED, myGREEN, myBLUE;
17 |
18 | // Input a value 0 to 255 to get a color value.
19 | // The colours are a transition r - g - b - back to r.
20 | // From: https://gist.github.com/davidegironi/3144efdc6d67e5df55438cc3cba613c8
21 | uint16_t colorWheel(uint8_t pos) {
22 | if(pos < 85) {
23 | return dma_display->color565(pos * 3, 255 - pos * 3, 0);
24 | } else if(pos < 170) {
25 | pos -= 85;
26 | return dma_display->color565(255 - pos * 3, 0, pos * 3);
27 | } else {
28 | pos -= 170;
29 | return dma_display->color565(0, pos * 3, 255 - pos * 3);
30 | }
31 | }
32 |
33 | void drawText(int colorWheelOffset)
34 | {
35 |
36 | // draw text with a rotating colour
37 | dma_display->setTextSize(1); // size 1 == 8 pixels high
38 | dma_display->setTextWrap(false); // Don't wrap at end of line - will do ourselves
39 |
40 | dma_display->setCursor(5, 0); // start at top left, with 8 pixel of spacing
41 | uint8_t w = 0;
42 | const char *str = "ESP32 DMA";
43 | for (w=0; wsetTextColor(colorWheel((w*32)+colorWheelOffset));
45 | dma_display->print(str[w]);
46 | }
47 |
48 | dma_display->println();
49 | dma_display->print(" ");
50 | for (w=9; w<18; w++) {
51 | dma_display->setTextColor(colorWheel((w*32)+colorWheelOffset));
52 | dma_display->print("*");
53 | }
54 |
55 | dma_display->println();
56 |
57 | dma_display->setTextColor(dma_display->color444(15,15,15));
58 | dma_display->println("LED MATRIX!");
59 |
60 | // print each letter with a fixed rainbow color
61 | dma_display->setTextColor(dma_display->color444(0,8,15));
62 | dma_display->print('3');
63 | dma_display->setTextColor(dma_display->color444(15,4,0));
64 | dma_display->print('2');
65 | dma_display->setTextColor(dma_display->color444(15,15,0));
66 | dma_display->print('x');
67 | dma_display->setTextColor(dma_display->color444(8,15,0));
68 | dma_display->print('6');
69 | dma_display->setTextColor(dma_display->color444(8,0,15));
70 | dma_display->print('4');
71 |
72 | // Jump a half character
73 | dma_display->setCursor(34, 24);
74 | dma_display->setTextColor(dma_display->color444(0,15,15));
75 | dma_display->print("*");
76 | dma_display->setTextColor(dma_display->color444(15,0,0));
77 | dma_display->print('R');
78 | dma_display->setTextColor(dma_display->color444(0,15,0));
79 | dma_display->print('G');
80 | dma_display->setTextColor(dma_display->color444(0,0,15));
81 | dma_display->print("B");
82 | dma_display->setTextColor(dma_display->color444(15,0,8));
83 | dma_display->println("*");
84 |
85 | }
86 |
87 |
88 | void setup() {
89 |
90 | // Module configuration
91 | HUB75_I2S_CFG mxconfig(
92 | PANEL_RES_X, // module width
93 | PANEL_RES_Y, // module height
94 | PANEL_CHAIN // Chain length
95 | );
96 |
97 | //mxconfig.gpio.e = 18;
98 | //mxconfig.clkphase = false;
99 | //mxconfig.driver = HUB75_I2S_CFG::FM6126A;
100 |
101 | // Display Setup
102 | dma_display = new MatrixPanel_I2S_DMA(mxconfig);
103 | dma_display->begin();
104 | dma_display->setBrightness8(90); //0-255
105 | dma_display->clearScreen();
106 |
107 | myBLACK = dma_display->color565(0, 0, 0);
108 | myWHITE = dma_display->color565(255, 255, 255);
109 | myRED = dma_display->color565(255, 0, 0);
110 | myGREEN = dma_display->color565(0, 255, 0);
111 | myBLUE = dma_display->color565(0, 0, 255);
112 |
113 |
114 | dma_display->fillScreen(myWHITE);
115 |
116 | // fix the screen with green
117 | dma_display->fillRect(0, 0, dma_display->width(), dma_display->height(), dma_display->color444(0, 15, 0));
118 | delay(500);
119 |
120 | // draw a box in yellow
121 | dma_display->drawRect(0, 0, dma_display->width(), dma_display->height(), dma_display->color444(15, 15, 0));
122 | delay(500);
123 |
124 | // draw an 'X' in red
125 | dma_display->drawLine(0, 0, dma_display->width()-1, dma_display->height()-1, dma_display->color444(15, 0, 0));
126 | dma_display->drawLine(dma_display->width()-1, 0, 0, dma_display->height()-1, dma_display->color444(15, 0, 0));
127 | delay(500);
128 |
129 | // draw a blue circle
130 | dma_display->drawCircle(10, 10, 10, dma_display->color444(0, 0, 15));
131 | delay(500);
132 |
133 | // fill a violet circle
134 | dma_display->fillCircle(40, 21, 10, dma_display->color444(15, 0, 15));
135 | delay(500);
136 |
137 | // fill the screen with 'black'
138 | dma_display->fillScreen(dma_display->color444(0, 0, 0));
139 |
140 | //drawText(0);
141 |
142 | }
143 |
144 | uint8_t wheelval = 0;
145 | void loop() {
146 |
147 | // animate by going through the colour wheel for the first two lines
148 | drawText(wheelval);
149 | wheelval +=1;
150 |
151 | delay(20);
152 | /*
153 | drawText(0);
154 | delay(2000);
155 | dma_display->clearScreen();
156 | dma_display->fillScreen(myBLACK);
157 | delay(2000);
158 | dma_display->fillScreen(myBLUE);
159 | delay(2000);
160 | dma_display->fillScreen(myRED);
161 | delay(2000);
162 | dma_display->fillScreen(myGREEN);
163 | delay(2000);
164 | dma_display->fillScreen(myWHITE);
165 | dma_display->clearScreen();
166 | */
167 |
168 | }
169 |
--------------------------------------------------------------------------------
/examples/2_PatternPlasma/PatternWave.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/2_PatternPlasma/PatternWave.jpg
--------------------------------------------------------------------------------
/examples/2_PatternPlasma/README.md:
--------------------------------------------------------------------------------
1 | # Wave Pattern
2 |
3 | Demo of the colours, and the little flicker.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/examples/3_DoubleBuffer/3_DoubleBuffer.ino:
--------------------------------------------------------------------------------
1 | /**
2 | Example uses the following configuration: mxconfig.double_buff = true;
3 | to enable double buffering, which means display->flipDMABuffer(); is required.
4 |
5 | Bounce squares around the screen, doing the re-drawing in the background back-buffer.
6 |
7 | Double buffering is not usually required. It is only useful when you have a long (in duration)
8 | drawing routine that you want to 'flip to' once complete without the drawing being visible to
9 | the naked eye when looking at the HUB75 panel.
10 |
11 | Please note that double buffering isn't a silver bullet, and may still result in flickering
12 | if you end up 'flipping' the buffer quicker than the physical HUB75 refresh output rate.
13 |
14 | Refer to the runtime debug output to see, i.e:
15 |
16 | [ 2103][I][ESP32-HUB75-MatrixPanel-I2S-DMA.cpp:85] setupDMA(): [I2S-DMA] Minimum visual refresh rate (scan rate from panel top to bottom) requested: 60 Hz
17 | [ 2116][W][ESP32-HUB75-MatrixPanel-I2S-DMA.cpp:105] setupDMA(): [I2S-DMA] lsbMsbTransitionBit of 0 gives 57 Hz refresh rate.
18 | [ 2128][W][ESP32-HUB75-MatrixPanel-I2S-DMA.cpp:105] setupDMA(): [I2S-DMA] lsbMsbTransitionBit of 1 gives 110 Hz refresh rate.
19 | [ 2139][W][ESP32-HUB75-MatrixPanel-I2S-DMA.cpp:118] setupDMA(): [I2S-DMA] lsbMsbTransitionBit of 1 used to achieve refresh rate of 60 Hz.
20 |
21 | **/
22 |
23 |
24 | #include
25 | #include
26 |
27 | MatrixPanel_I2S_DMA *display = nullptr;
28 |
29 | constexpr std::size_t color_num = 5;
30 | using colour_arr_t = std::array;
31 |
32 | uint16_t myDARK, myWHITE, myRED, myGREEN, myBLUE;
33 | colour_arr_t colours;
34 |
35 | struct Square
36 | {
37 | float xpos, ypos;
38 | float velocityx;
39 | float velocityy;
40 | boolean xdir, ydir;
41 | uint16_t square_size;
42 | uint16_t colour;
43 | };
44 |
45 | const int numSquares = 25;
46 | Square Squares[numSquares];
47 |
48 | void setup()
49 | {
50 | // put your setup code here, to run once:
51 | delay(1000);
52 | Serial.begin(115200);
53 | delay(200);
54 |
55 | Serial.println("...Starting Display");
56 | HUB75_I2S_CFG mxconfig;
57 | mxconfig.double_buff = true; // <------------- Turn on double buffer
58 | //mxconfig.clkphase = false; // <------------- Turn off double buffer and it'll look flickery
59 |
60 | // OK, now we can create our matrix object
61 | display = new MatrixPanel_I2S_DMA(mxconfig);
62 | display->begin(); // setup display with pins as pre-defined in the library
63 |
64 | myDARK = display->color565(64, 64, 64);
65 | myWHITE = display->color565(192, 192, 192);
66 | myRED = display->color565(255, 0, 0);
67 | myGREEN = display->color565(0, 255, 0);
68 | myBLUE = display->color565(0, 0, 255);
69 |
70 | colours = {{ myDARK, myWHITE, myRED, myGREEN, myBLUE }};
71 |
72 | // Create some random squares
73 | for (int i = 0; i < numSquares; i++)
74 | {
75 | Squares[i].square_size = random(2,10);
76 | Squares[i].xpos = random(0, display->width() - Squares[i].square_size);
77 | Squares[i].ypos = random(0, display->height() - Squares[i].square_size);
78 | Squares[i].velocityx = static_cast (rand()) / static_cast (RAND_MAX);
79 | Squares[i].velocityy = static_cast (rand()) / static_cast (RAND_MAX);
80 |
81 | int random_num = random(6);
82 | Squares[i].colour = colours[random_num];
83 | }
84 | }
85 |
86 | void loop()
87 | {
88 |
89 | // Flip all future drawPixel calls to write to the back buffer which is NOT being displayed.
90 | display->flipDMABuffer();
91 |
92 | // SUPER IMPORTANT: Wait at least long enough to ensure that a "frame" has been displayed on the LED Matrix Panel before the next flip!
93 | delay(1000/display->calculated_refresh_rate);
94 |
95 | // Now clear the back-buffer we are drawing to.
96 | display->clearScreen();
97 |
98 | // This is here to demonstrate flicker if double buffering is disabled. Emulates a long draw routine that would typically occur after a 'clearscreen'.
99 | delay(25);
100 |
101 |
102 | for (int i = 0; i < numSquares; i++)
103 | {
104 | // Draw rect and then calculate
105 | display->fillRect(Squares[i].xpos, Squares[i].ypos, Squares[i].square_size, Squares[i].square_size, Squares[i].colour);
106 |
107 | if (Squares[i].square_size + Squares[i].xpos >= display->width()) {
108 | Squares[i].velocityx *= -1;
109 | } else if (Squares[i].xpos <= 0) {
110 | Squares[i].velocityx = abs (Squares[i].velocityx);
111 | }
112 |
113 | if (Squares[i].square_size + Squares[i].ypos >= display->height()) {
114 | Squares[i].velocityy *= -1;
115 | } else if (Squares[i].ypos <= 0) {
116 | Squares[i].velocityy = abs (Squares[i].velocityy);
117 | }
118 |
119 | Squares[i].xpos += Squares[i].velocityx;
120 | Squares[i].ypos += Squares[i].velocityy;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/examples/4_OtherShiftDriverPanel/4_OtherShiftDriverPanel.ino:
--------------------------------------------------------------------------------
1 | /**********************************************************************
2 | * The library by default supports simple 'shift register' based panels
3 | * with A,B,C,D,E lines to select a specific row, but there are plenty
4 | * of examples of new chips coming on the market that work different.
5 | *
6 | * Please search through the project's issues. For some of these chips
7 | * (you will need to look at the back of your panel to identify), this
8 | * library has workarounds. This can be configured through using one of:
9 |
10 | // mxconfig.driver = HUB75_I2S_CFG::FM6126A;
11 | //mxconfig.driver = HUB75_I2S_CFG::ICN2038S;
12 | //mxconfig.driver = HUB75_I2S_CFG::FM6124;
13 | //mxconfig.driver = HUB75_I2S_CFG::MBI5124;
14 | */
15 |
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | ////////////////////////////////////////////////////////////////////
22 |
23 | // Output resolution and panel chain length configuration
24 | #define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
25 | #define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
26 | #define PANEL_CHAIN 1 // Total number of panels chained one to another
27 |
28 | // placeholder for the matrix object
29 | MatrixPanel_I2S_DMA *dma_display = nullptr;
30 |
31 | ///////////////////////////////////////////////////////////////
32 |
33 | // FastLED variables for pattern output
34 | uint16_t time_counter = 0, cycles = 0, fps = 0;
35 | unsigned long fps_timer;
36 |
37 | CRGB currentColor;
38 | CRGBPalette16 palettes[] = {HeatColors_p, LavaColors_p, RainbowColors_p, RainbowStripeColors_p, CloudColors_p};
39 | CRGBPalette16 currentPalette = palettes[0];
40 |
41 |
42 | CRGB ColorFromCurrentPalette(uint8_t index = 0, uint8_t brightness = 255, TBlendType blendType = LINEARBLEND) {
43 | return ColorFromPalette(currentPalette, index, brightness, blendType);
44 | }
45 |
46 | void setup(){
47 |
48 | HUB75_I2S_CFG mxconfig(
49 | PANEL_RES_X, // module width
50 | PANEL_RES_Y, // module height
51 | PANEL_CHAIN // Chain length
52 | );
53 |
54 | // in case that we use panels based on FM6126A chip, we can set it here before creating MatrixPanel_I2S_DMA object
55 | mxconfig.driver = HUB75_I2S_CFG::FM6126A;
56 | //mxconfig.driver = HUB75_I2S_CFG::ICN2038S;
57 | //mxconfig.driver = HUB75_I2S_CFG::FM6124;
58 | //mxconfig.driver = HUB75_I2S_CFG::MBI5124;
59 |
60 |
61 | // OK, now we can create our matrix object
62 | dma_display = new MatrixPanel_I2S_DMA(mxconfig);
63 |
64 | // If you experience ghosting, you will need to reduce the brightness level, not all RGB Matrix
65 | // Panels are the same - some seem to display ghosting artefacts at lower brightness levels.
66 | // In the setup() function do something like:
67 |
68 | // let's adjust default brightness to about 75%
69 | dma_display->setBrightness8(192); // range is 0-255, 0 - 0%, 255 - 100%
70 |
71 | // Allocate memory and start DMA display
72 | if( not dma_display->begin() )
73 | Serial.println("****** !KABOOM! Insufficient memory - allocation failed ***********");
74 |
75 | fps_timer = millis();
76 |
77 | }
78 |
79 | void loop(){
80 | for (int x = 0; x < dma_display->width(); x++) {
81 | for (int y = 0; y < dma_display->height(); y++) {
82 | int16_t v = 0;
83 | uint8_t wibble = sin8(time_counter);
84 | v += sin16(x * wibble * 3 + time_counter);
85 | v += cos16(y * (128 - wibble) + time_counter);
86 | v += sin16(y * x * cos8(-time_counter) / 8);
87 |
88 | currentColor = ColorFromPalette(currentPalette, (v >> 8) + 127); //, brightness, currentBlendType);
89 | dma_display->drawPixelRGB888(x, y, currentColor.r, currentColor.g, currentColor.b);
90 | }
91 | }
92 |
93 | ++time_counter;
94 | ++cycles;
95 | ++fps;
96 |
97 | if (cycles >= 1024) {
98 | time_counter = 0;
99 | cycles = 0;
100 | currentPalette = palettes[random(0,sizeof(palettes)/sizeof(palettes[0]))];
101 | }
102 |
103 | // print FPS rate every 5 seconds
104 | // Note: this is NOT a matrix refresh rate, it's the number of data frames being drawn to the DMA buffer per second
105 | if (fps_timer + 5000 < millis()){
106 | Serial.printf_P(PSTR("Effect fps: %d\n"), fps/5);
107 | fps_timer = millis();
108 | fps = 0;
109 | }
110 | }
111 |
112 |
113 | // FM6126 panel , thanks goes to:
114 | // https://github.com/hzeller/rpi-rgb-led-matrix/issues/746
115 |
--------------------------------------------------------------------------------
/examples/4_OtherShiftDriverPanel/FM6126A.md:
--------------------------------------------------------------------------------
1 | ## The mystery of control registers for FM6126A chips
2 |
3 |
4 | The only available Datasheet for this chips is in Chinese and does not shed a light on what those two control regs are.
5 |
6 | An excellent insight could be found here https://github.com/hzeller/rpi-rgb-led-matrix/issues/746#issuecomment-453860510
7 |
8 |
9 |
10 | So there are two regs in this chip - **REG1** and **REG2**,
11 | one could be written with 12 clock pulses (and usually called reg12, dunno why :))
12 | the other one could be written with 13 clock pulses (and usually called reg13, dunno why :))
13 |
14 |
15 | I've done some measurements on power consumption while toggling bits of **REG1** and it looks that it could provide a fine grained brightness control over the entire matrix with no need for bitbanging over RGB or EO pins.
16 | There are 6 bits (6 to 11) giving an increased brightness (compared to all-zeroes) and 4 bits (2-5) giving decreased brightness!!!
17 | Still unclear if FM6112A brightness control is internally PWMed or current limited, might require some poking with oscilloscope.
18 |
19 | So it seems that the most bright (and hungry for power) value is bool REG1[16] = {0,0,0,0,0, 1,1,1,1,1,1, 0,0,0,0,0}; and not {0,1,1,1,1, 1,1,1,1,1,1, 1,1,1,1,1} as it is usually used.
20 | I'm not sure about bit 1 - it is either not used or I was unable to measure it's influence to brightness/power.
21 |
22 | Giving at least 10 bits of hardware brightness control opens pretty nice options for offloading and simplifying matrix output. Should dig into this more deeper.
23 |
24 | Here are some of the measurements I've took for 2 64x64 panels filled with white color - reg value and corresponding current drain in amps.
25 |
26 |
27 | |REG1 |bit value|Current, amps |
28 | |--|--|--|
29 | |REG1| 0111111 00000| >5 amps|
30 | |REG1| 0100010 00000| 3.890 amp|
31 | |REG1| 0100000 00000| 3.885 amp|
32 | |REG1| 0011110 00000| 3.640 amp|
33 | |REG1| 0011100 00000| 3.620 amp|
34 | |REG1| 0011000 00000| 3.240 amp|
35 | |REG1| 0010010 00000| 2.520 amp|
36 | |REG1| 0010001 00000| 2.518 amp|
37 | |REG1| 0010001 10000| 2.493 amp|
38 | |REG1| 0010000 00000| 2.490 amp|
39 | |REG1| 0010000 11110| 2.214 amp|
40 | |REG1| 0001100 00000| 2.120 amp|
41 | |REG1| 0001000 00000| 1.750 amp|
42 | |REG1| 0000100 00000| 1.375 amp|
43 | |REG1| 0000010 00000| 1.000 amp|
44 | |REG1| **0000000 00000**| 0.995 amp|
45 | |REG1| 0000001 11111| 0.700 amp|
46 | |REG1| 0000000 01111| 0.690 amp|
47 | |REG1| 0000000 10000| 0.690 amp|
48 | |REG1| 0000000 11110| 0.686 amp|
49 |
50 |
51 | /Vortigont/
--------------------------------------------------------------------------------
/examples/4_OtherShiftDriverPanel/README.md:
--------------------------------------------------------------------------------
1 | ## Other driver based LED Matrix Panels ##
2 |
3 | Limited support for other panels exists, but requires this to be passed as a configuration option when using the library.
4 |
5 | These panels require a special reset sequence before they can be used, check your panel chipset if you have issues. Refer to the example.
6 |
7 |
8 | ```
9 | mxconfig.driver = HUB75_I2S_CFG::FM6126A;
10 | mxconfig.driver = HUB75_I2S_CFG::ICN2038S;
11 | mxconfig.driver = HUB75_I2S_CFG::FM6124;
12 | mxconfig.driver = HUB75_I2S_CFG::MBI5124;
13 | ```
14 |
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_LittleFS/README.md:
--------------------------------------------------------------------------------
1 | ## Animated GIF Decoding Example
2 |
3 | ### Prerequisites
4 | 1. The excellent 'AnimatedGIF' library by Larry Bank needs to be installed: https://github.com/bitbank2/AnimatedGIF
5 |
6 | 2. The files in the 'data' folder are written to the ESP32's SPIFFS file system. In order to be able to do this using the Arduino 2.0 IDE, you need to install the ESP32 LittleFS plugin: https://github.com/lorol/arduino-esp32littlefs-plugin
7 |
8 | Follow the instructions in the link to install the plugin: https://randomnerdtutorials.com/arduino-ide-2-install-esp32-littlefs/
9 |
10 |
11 | ## Credits
12 |
13 | https://github.com/bitbank2/AnimatedGIF
14 |
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_LittleFS/data/gifs/cartoon.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_LittleFS/data/gifs/cartoon.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_LittleFS/data/gifs/ezgif.com-pacmn.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_LittleFS/data/gifs/ezgif.com-pacmn.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_LittleFS/data/gifs/loading.io-64x32px.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_LittleFS/data/gifs/loading.io-64x32px.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_LittleFS/data/gifs/matrix-spin.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_LittleFS/data/gifs/matrix-spin.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_LittleFS/data/gifs/parasite1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_LittleFS/data/gifs/parasite1.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_LittleFS/data/gifs/parasite2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_LittleFS/data/gifs/parasite2.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_LittleFS/data/gifs/shock-gs.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_LittleFS/data/gifs/shock-gs.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/Readme.md:
--------------------------------------------------------------------------------
1 | # ESP32-HUB75-MatrixPanel-DMA SDCard example
2 |
3 | A very basic example using the 'Animated GIF' library by Larry Bank + the SD / File system library provided for Arduino by Espressif.
4 |
5 | Some default HUB75 pins need to be remapped to accomodate for the SD Card.
6 |
7 | 
8 |
9 | ## How to use it?
10 |
11 | 1. Format a SD Card with FAT32 file system (default setting)
12 | 2. Create a directory called 'gifs'
13 | 3. Drop your gifs in there. The resolution of the GIFS must match that of the display.
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/esp32_sdcard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_SD/esp32_sdcard.jpg
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/gif_functions.hpp:
--------------------------------------------------------------------------------
1 |
2 | // Code copied from AnimatedGIF examples
3 |
4 | #ifndef M5STACK_SD
5 | // for custom ESP32 builds
6 | #define M5STACK_SD SD
7 | #endif
8 |
9 |
10 | static void * GIFOpenFile(const char *fname, int32_t *pSize)
11 | {
12 | //log_d("GIFOpenFile( %s )\n", fname );
13 | FSGifFile = M5STACK_SD.open(fname);
14 | if (FSGifFile) {
15 | *pSize = FSGifFile.size();
16 | return (void *)&FSGifFile;
17 | }
18 | return NULL;
19 | }
20 |
21 |
22 | static void GIFCloseFile(void *pHandle)
23 | {
24 | File *f = static_cast(pHandle);
25 | if (f != NULL)
26 | f->close();
27 | }
28 |
29 |
30 | static int32_t GIFReadFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen)
31 | {
32 | int32_t iBytesRead;
33 | iBytesRead = iLen;
34 | File *f = static_cast(pFile->fHandle);
35 | // Note: If you read a file all the way to the last byte, seek() stops working
36 | if ((pFile->iSize - pFile->iPos) < iLen)
37 | iBytesRead = pFile->iSize - pFile->iPos - 1; // <-- ugly work-around
38 | if (iBytesRead <= 0)
39 | return 0;
40 | iBytesRead = (int32_t)f->read(pBuf, iBytesRead);
41 | pFile->iPos = f->position();
42 | return iBytesRead;
43 | }
44 |
45 |
46 | static int32_t GIFSeekFile(GIFFILE *pFile, int32_t iPosition)
47 | {
48 | int i = micros();
49 | File *f = static_cast(pFile->fHandle);
50 | f->seek(iPosition);
51 | pFile->iPos = (int32_t)f->position();
52 | i = micros() - i;
53 | //log_d("Seek time = %d us\n", i);
54 | return pFile->iPos;
55 | }
56 |
57 |
58 | // Draw a line of image directly on the LCD
59 | void GIFDraw(GIFDRAW *pDraw)
60 | {
61 | uint8_t *s;
62 | uint16_t *d, *usPalette, usTemp[320];
63 | int x, y, iWidth;
64 |
65 | iWidth = pDraw->iWidth;
66 | if (iWidth > PANEL_RES_X)
67 | iWidth = PANEL_RES_X;
68 | usPalette = pDraw->pPalette;
69 | y = pDraw->iY + pDraw->y; // current line
70 |
71 | s = pDraw->pPixels;
72 | if (pDraw->ucDisposalMethod == 2) {// restore to background color
73 | for (x=0; xucTransparent)
75 | s[x] = pDraw->ucBackground;
76 | }
77 | pDraw->ucHasTransparency = 0;
78 | }
79 | // Apply the new pixels to the main image
80 | if (pDraw->ucHasTransparency) { // if transparency used
81 | uint8_t *pEnd, c, ucTransparent = pDraw->ucTransparent;
82 | int x, iCount;
83 | pEnd = s + iWidth;
84 | x = 0;
85 | iCount = 0; // count non-transparent pixels
86 | while(x < iWidth) {
87 | c = ucTransparent-1;
88 | d = usTemp;
89 | while (c != ucTransparent && s < pEnd) {
90 | c = *s++;
91 | if (c == ucTransparent) { // done, stop
92 | s--; // back up to treat it like transparent
93 | } else { // opaque
94 | *d++ = usPalette[c];
95 | iCount++;
96 | }
97 | } // while looking for opaque pixels
98 | if (iCount) { // any opaque pixels?
99 | for(int xOffset = 0; xOffset < iCount; xOffset++ ){
100 | dma_display->drawPixel(x + xOffset, y, usTemp[xOffset]); // 565 Color Format
101 | }
102 | x += iCount;
103 | iCount = 0;
104 | }
105 | // no, look for a run of transparent pixels
106 | c = ucTransparent;
107 | while (c == ucTransparent && s < pEnd) {
108 | c = *s++;
109 | if (c == ucTransparent)
110 | iCount++;
111 | else
112 | s--;
113 | }
114 | if (iCount) {
115 | x += iCount; // skip these
116 | iCount = 0;
117 | }
118 | }
119 | } else {
120 | s = pDraw->pPixels;
121 | // Translate the 8-bit pixels through the RGB565 palette (already byte reversed)
122 | for (x=0; xdrawPixel(x, y, usPalette[*s++]); // color 565
124 | /*
125 | usTemp[x] = usPalette[*s++];
126 |
127 | for (x=0; xiWidth; x++) {
128 | dma_display->drawPixel(x, y, usTemp[*s++]); // color 565
129 | } */
130 |
131 | }
132 | } /* GIFDraw() */
133 |
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/gifs/cartoon.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_SD/gifs/cartoon.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/gifs/ezgif.com-pacmn.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_SD/gifs/ezgif.com-pacmn.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/gifs/loading.io-64x32px.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_SD/gifs/loading.io-64x32px.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/gifs/matrix-spin.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_SD/gifs/matrix-spin.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/gifs/parasite1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_SD/gifs/parasite1.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/gifs/parasite2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_SD/gifs/parasite2.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/gifs/shock-gs.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/AnimatedGIFPanel_SD/gifs/shock-gs.gif
--------------------------------------------------------------------------------
/examples/AnimatedGIFPanel_SD/sdcard_functions.hpp:
--------------------------------------------------------------------------------
1 | /************************ SD Card Code ************************/
2 | // As per: https://github.com/espressif/arduino-esp32/tree/master/libraries/SD/examples/SD_Test
3 |
4 |
5 |
6 | void listDir(fs::FS &fs, const char * dirname, uint8_t levels, bool add_to_gif_list = false){
7 | Serial.printf("Listing directory: %s\n", dirname);
8 |
9 | File root = fs.open(dirname);
10 | if(!root){
11 | Serial.println("Failed to open directory");
12 | return;
13 | }
14 | if(!root.isDirectory()){
15 | Serial.println("Not a directory");
16 | return;
17 | }
18 |
19 | File file = root.openNextFile();
20 | while(file){
21 | if(file.isDirectory()){
22 | Serial.print(" DIR : ");
23 | Serial.println(file.name());
24 | if(levels){
25 | listDir(fs, file.path(), levels -1, false);
26 | }
27 | } else {
28 | Serial.print(" FILE: ");
29 | Serial.print(file.name());
30 | Serial.print(" SIZE: ");
31 | Serial.println(file.size());
32 |
33 | if (add_to_gif_list && levels == 0)
34 | {
35 | GifFiles.push_back( std::string(dirname) + file.name() );
36 | Serial.println("Adding to gif list:" + String(dirname) +"/" + file.name());
37 | totalFiles++;
38 | }
39 | }
40 | file = root.openNextFile();
41 | }
42 |
43 | file.close();
44 | }
45 |
46 | void readFile(fs::FS &fs, const char * path){
47 | Serial.printf("Reading file: %s\n", path);
48 |
49 | File file = fs.open(path);
50 | if(!file){
51 | Serial.println("Failed to open file for reading");
52 | return;
53 | }
54 |
55 | Serial.print("Read from file: ");
56 | while(file.available()){
57 | Serial.write(file.read());
58 | }
59 | file.close();
60 | }
61 |
62 | void testFileIO(fs::FS &fs, const char * path){
63 | File file = fs.open(path);
64 | static uint8_t buf[512];
65 | size_t len = 0;
66 | uint32_t start = millis();
67 | uint32_t end = start;
68 | if(file){
69 | len = file.size();
70 | size_t flen = len;
71 | start = millis();
72 | while(len){
73 | size_t toRead = len;
74 | if(toRead > 512){
75 | toRead = 512;
76 | }
77 | file.read(buf, toRead);
78 | len -= toRead;
79 | }
80 | end = millis() - start;
81 | Serial.printf("%u bytes read for %u ms\n", flen, end);
82 | file.close();
83 | } else {
84 | Serial.println("Failed to open file for reading");
85 | }
86 |
87 |
88 | file = fs.open(path, FILE_WRITE);
89 | if(!file){
90 | Serial.println("Failed to open file for writing");
91 | return;
92 | }
93 |
94 | size_t i;
95 | start = millis();
96 | for(i=0; i<2048; i++){
97 | file.write(buf, 512);
98 | }
99 | end = millis() - start;
100 | Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
101 | file.close();
102 | }
--------------------------------------------------------------------------------
/examples/AuroraDemo/Attractor.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Portions of this code are adapted from "Attractor" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/
6 | * Copyright (c) 2014 Daniel Shiffman
7 | * http://www.shiffman.net
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
10 | * this software and associated documentation files (the "Software"), to deal in
11 | * the Software without restriction, including without limitation the rights to
12 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13 | * the Software, and to permit persons to whom the Software is furnished to do so,
14 | * subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in all
17 | * copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 | */
26 |
27 | #include "Vector2.hpp"
28 |
29 | class Attractor {
30 | public:
31 | float mass; // Mass, tied to size
32 | float G; // Gravitational Constant
33 | PVector location; // Location
34 |
35 | Attractor() {
36 | location = PVector(effects.getCenterX(), effects.getCenterY());
37 | mass = 10;
38 | G = .5;
39 | }
40 |
41 | PVector attract(Boid m) {
42 | PVector force = location - m.location; // Calculate direction of force
43 | float d = force.mag(); // Distance between objects
44 | d = constrain(d, 5.0, 32.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
45 | force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
46 | float strength = (G * mass * m.mass) / (d * d); // Calculate gravitational force magnitude
47 | force *= strength; // Get force vector --> magnitude * direction
48 | return force;
49 | }
50 | };
51 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/Drawable.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef Drawable_H
24 | #define Drawable_H
25 |
26 | class Drawable{
27 | public:
28 | char* name;
29 |
30 | virtual bool isRunnable() {
31 | return false;
32 | }
33 |
34 | virtual bool isPlaylist() {
35 | return false;
36 | }
37 |
38 | // a single frame should be drawn as fast as possible, without any delay or blocking
39 | // return how many millisecond delay is requested before the next call to drawFrame()
40 | virtual unsigned int drawFrame() {
41 | matrix->fillScreen(0);
42 | //backgroundLayer.fillScreen({ 0, 0, 0 });
43 | return 0;
44 | };
45 |
46 | virtual void printTesting()
47 | {
48 | Serial.println("Testing...");
49 | }
50 |
51 | virtual void start() {};
52 | virtual void stop() {};
53 | };
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/Geometry.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Portions of this code are adapted from Noel Bundy's work: https://github.com/TwystNeko/Object3d
6 | * Copyright (c) 2014 Noel Bundy
7 | *
8 | * Portions of this code are adapted from the Petty library: https://code.google.com/p/peggy/
9 | * Copyright (c) 2008 Windell H Oskay. All right reserved.
10 | *
11 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
12 | * this software and associated documentation files (the "Software"), to deal in
13 | * the Software without restriction, including without limitation the rights to
14 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
15 | * the Software, and to permit persons to whom the Software is furnished to do so,
16 | * subject to the following conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be included in all
19 | * copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
23 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
24 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | */
28 |
29 | #ifndef Geometry_H
30 | #define Geometry_H
31 |
32 | struct Vertex
33 | {
34 | float x, y, z;
35 | Vertex()
36 | {
37 | this->set(0, 0, 0);
38 | }
39 |
40 | Vertex(float x, float y, float z)
41 | {
42 | this->set(x, y, z);
43 | }
44 |
45 | void set(float x, float y, float z)
46 | {
47 | this->x = x;
48 | this->y = y;
49 | this->z = z;
50 | }
51 | };
52 |
53 | struct EdgePoint
54 | {
55 | int x, y;
56 | boolean visible;
57 |
58 | EdgePoint()
59 | {
60 | this->set(0, 0);
61 | this->visible = false;
62 | }
63 |
64 | void set(int a, int b)
65 | {
66 | this->x = a;
67 | this->y = b;
68 | }
69 | };
70 |
71 | struct Point
72 | {
73 | float x, y;
74 |
75 | Point()
76 | {
77 | set(0, 0);
78 | }
79 |
80 | Point(float x, float y)
81 | {
82 | set(x, y);
83 | }
84 |
85 | void set(float x, float y)
86 | {
87 | this->x = x;
88 | this->y = y;
89 | }
90 |
91 | };
92 |
93 | struct squareFace
94 | {
95 | int length;
96 | int sommets[4];
97 | int ed[4];
98 |
99 | squareFace()
100 | {
101 | set(-1, -1, -1, -1);
102 | }
103 |
104 | squareFace(int a, int b, int c, int d)
105 | {
106 | this->length = 4;
107 | this->sommets[0] = a;
108 | this->sommets[1] = b;
109 | this->sommets[2] = c;
110 | this->sommets[3] = d;
111 | }
112 |
113 | void set(int a, int b, int c, int d)
114 | {
115 | this->length = 4;
116 | this->sommets[0] = a;
117 | this->sommets[1] = b;
118 | this->sommets[2] = c;
119 | this->sommets[3] = d;
120 | }
121 |
122 | };
123 |
124 | struct triFace
125 | {
126 | int length;
127 | int sommets[3];
128 | int ed[3];
129 |
130 | triFace()
131 | {
132 | set(-1,-1,-1);
133 | }
134 | triFace(int a, int b, int c)
135 | {
136 | this->length =3;
137 | this->sommets[0]=a;
138 | this->sommets[1]=b;
139 | this->sommets[2]=c;
140 | }
141 | void set(int a, int b, int c)
142 | {
143 | this->length =3;
144 | this->sommets[0]=a;
145 | this->sommets[1]=b;
146 | this->sommets[2]=c;
147 | }
148 | };
149 |
150 | #endif
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternAttract.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef PatternAttract_H
24 |
25 | class PatternAttract : public Drawable {
26 | private:
27 | const int count = AVAILABLE_BOID_COUNT-1;
28 | Attractor attractor;
29 |
30 | public:
31 | PatternAttract() {
32 | name = (char *)"Attract";
33 | }
34 |
35 | void start() {
36 | int direction = random(0, 2);
37 | if (direction == 0)
38 | direction = -1;
39 |
40 | for (int i = 0; i < count; i++) {
41 | Boid boid = Boid(VPANEL_W/2, VPANEL_H - i);
42 | boid.mass = 1; // random(0.1, 2);
43 | boid.velocity.x = ((float) random(40, 50)) / 100.0;
44 | boid.velocity.x *= direction;
45 | boid.velocity.y = 0;
46 | boid.colorIndex = i * 32;
47 | boids[i] = boid;
48 | //dim = random(170, 250);
49 | }
50 | }
51 |
52 | unsigned int drawFrame() {
53 | // dim all pixels on the display
54 | uint8_t dim = beatsin8(2, 170, 250);
55 | effects.DimAll(dim);
56 |
57 | for (int i = 0; i < count; i++) {
58 | Boid boid = boids[i];
59 |
60 | PVector force = attractor.attract(boid);
61 | boid.applyForce(force);
62 |
63 | boid.update();
64 | effects.setPixel(boid.location.x, boid.location.y, effects.ColorFromCurrentPalette(boid.colorIndex));
65 |
66 | boids[i] = boid;
67 | }
68 |
69 | effects.ShowFrame();
70 | return 0;
71 | }
72 | };
73 |
74 | #endif
75 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternBounce.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef PatternBounce_H
24 |
25 | class PatternBounce : public Drawable {
26 | private:
27 | static const int count = VPANEL_W-1;
28 | PVector gravity = PVector(0, 0.0125);
29 |
30 | public:
31 | PatternBounce() {
32 | name = (char *)"Bounce";
33 | }
34 |
35 | void start() {
36 | unsigned int colorWidth = 256 / count;
37 | for (int i = 0; i < count; i++) {
38 | Boid boid = Boid(i, 0);
39 | boid.velocity.x = 0;
40 | boid.velocity.y = i * -0.01;
41 | boid.colorIndex = colorWidth * i;
42 | boid.maxforce = 10;
43 | boid.maxspeed = 10;
44 | boids[i] = boid;
45 | }
46 | }
47 |
48 | unsigned int drawFrame() {
49 | // dim all pixels on the display
50 | effects.DimAll(170); effects.ShowFrame();
51 |
52 | for (int i = 0; i < count; i++) {
53 | Boid boid = boids[i];
54 |
55 | boid.applyForce(gravity);
56 |
57 | boid.update();
58 |
59 | effects.setPixel(boid.location.x, boid.location.y, effects.ColorFromCurrentPalette(boid.colorIndex));
60 |
61 | if (boid.location.y >= VPANEL_H - 1) {
62 | boid.location.y = VPANEL_H - 1;
63 | boid.velocity.y *= -1.0;
64 | }
65 |
66 | boids[i] = boid;
67 | }
68 |
69 | return 15;
70 | }
71 | };
72 |
73 | #endif
74 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternCube.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Portions of this code are adapted from Noel Bundy's work: https://github.com/TwystNeko/Object3d
6 | * Copyright (c) 2014 Noel Bundy
7 | *
8 | * Portions of this code are adapted from the Petty library: https://code.google.com/p/peggy/
9 | * Copyright (c) 2008 Windell H Oskay. All right reserved.
10 | *
11 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
12 | * this software and associated documentation files (the "Software"), to deal in
13 | * the Software without restriction, including without limitation the rights to
14 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
15 | * the Software, and to permit persons to whom the Software is furnished to do so,
16 | * subject to the following conditions:
17 | *
18 | * The above copyright notice and this permission notice shall be included in all
19 | * copies or substantial portions of the Software.
20 | *
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
23 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
24 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | */
28 |
29 | #ifndef PatternCube_H
30 | #define PatternCube_H
31 |
32 | class PatternCube : public Drawable {
33 | private:
34 | float focal = 30; // Focal of the camera
35 | int cubeWidth = 28; // Cube size
36 | float Angx = 20.0, AngxSpeed = 0.05; // rotation (angle+speed) around X-axis
37 | float Angy = 10.0, AngySpeed = 0.05; // rotation (angle+speed) around Y-axis
38 | float Ox = VPANEL_W/2, Oy = VPANEL_H/2; // position (x,y) of the frame center
39 | int zCamera = 110; // distance from cube to the eye of the camera
40 |
41 | // Local vertices
42 | Vertex local[8];
43 | // Camera aligned vertices
44 | Vertex aligned[8];
45 | // On-screen projected vertices
46 | Point screen[8];
47 | // Faces
48 | squareFace face[6];
49 | // Edges
50 | EdgePoint edge[12];
51 | int nbEdges;
52 | // ModelView matrix
53 | float m00, m01, m02, m10, m11, m12, m20, m21, m22;
54 |
55 | // constructs the cube
56 | void make(int w)
57 | {
58 | nbEdges = 0;
59 |
60 | local[0].set(-w, w, w);
61 | local[1].set(w, w, w);
62 | local[2].set(w, -w, w);
63 | local[3].set(-w, -w, w);
64 | local[4].set(-w, w, -w);
65 | local[5].set(w, w, -w);
66 | local[6].set(w, -w, -w);
67 | local[7].set(-w, -w, -w);
68 |
69 | face[0].set(1, 0, 3, 2);
70 | face[1].set(0, 4, 7, 3);
71 | face[2].set(4, 0, 1, 5);
72 | face[3].set(4, 5, 6, 7);
73 | face[4].set(1, 2, 6, 5);
74 | face[5].set(2, 3, 7, 6);
75 |
76 | int f, i;
77 | for (f = 0; f < 6; f++)
78 | {
79 | for (i = 0; i < face[f].length; i++)
80 | {
81 | face[f].ed[i] = this->findEdge(face[f].sommets[i], face[f].sommets[i ? i - 1 : face[f].length - 1]);
82 | }
83 | }
84 | }
85 |
86 | // finds edges from faces
87 | int findEdge(int a, int b)
88 | {
89 | int i;
90 | for (i = 0; i < nbEdges; i++)
91 | if ((edge[i].x == a && edge[i].y == b) || (edge[i].x == b && edge[i].y == a))
92 | return i;
93 | edge[nbEdges++].set(a, b);
94 | return i;
95 | }
96 |
97 | // rotates according to angle x&y
98 | void rotate(float angx, float angy)
99 | {
100 | int i;
101 | float cx = cos(angx);
102 | float sx = sin(angx);
103 | float cy = cos(angy);
104 | float sy = sin(angy);
105 |
106 | m00 = cy;
107 | m01 = 0;
108 | m02 = -sy;
109 | m10 = sx * sy;
110 | m11 = cx;
111 | m12 = sx * cy;
112 | m20 = cx * sy;
113 | m21 = -sx;
114 | m22 = cx * cy;
115 |
116 | for (i = 0; i < 8; i++)
117 | {
118 | aligned[i].x = m00 * local[i].x + m01 * local[i].y + m02 * local[i].z;
119 | aligned[i].y = m10 * local[i].x + m11 * local[i].y + m12 * local[i].z;
120 | aligned[i].z = m20 * local[i].x + m21 * local[i].y + m22 * local[i].z + zCamera;
121 |
122 | screen[i].x = floor((Ox + focal * aligned[i].x / aligned[i].z));
123 | screen[i].y = floor((Oy - focal * aligned[i].y / aligned[i].z));
124 | }
125 |
126 | for (i = 0; i < 12; i++)
127 | edge[i].visible = false;
128 |
129 | Point *pa, *pb, *pc;
130 | for (i = 0; i < 6; i++)
131 | {
132 | pa = screen + face[i].sommets[0];
133 | pb = screen + face[i].sommets[1];
134 | pc = screen + face[i].sommets[2];
135 |
136 | boolean back = ((pb->x - pa->x) * (pc->y - pa->y) - (pb->y - pa->y) * (pc->x - pa->x)) < 0;
137 | if (!back)
138 | {
139 | int j;
140 | for (j = 0; j < 4; j++)
141 | {
142 | edge[face[i].ed[j]].visible = true;
143 | }
144 | }
145 | }
146 | }
147 |
148 | byte hue = 0;
149 | int step = 0;
150 |
151 | public:
152 | PatternCube() {
153 | name = (char *)"Cube";
154 | make(VPANEL_W);
155 | }
156 |
157 | unsigned int drawFrame() {
158 | uint8_t blurAmount = beatsin8(2, 10, 128);
159 |
160 | #if FASTLED_VERSION >= 3001000
161 | blur2d(effects.leds, VPANEL_W, VPANEL_H, blurAmount);
162 | #else
163 | effects.DimAll(blurAmount); effects.ShowFrame();
164 | #endif
165 |
166 | zCamera = beatsin8(2, 100, 140);
167 | AngxSpeed = beatsin8(3, 1, 6) / 100.0f;
168 | AngySpeed = effects.beatcos8(5, 1, 6) / 100.0f;
169 |
170 | // Update values
171 | Angx += AngxSpeed;
172 | Angy += AngySpeed;
173 | if (Angx >= TWO_PI)
174 | Angx -= TWO_PI;
175 | if (Angy >= TWO_PI)
176 | Angy -= TWO_PI;
177 |
178 | rotate(Angx, Angy);
179 |
180 | // Draw cube
181 | int i;
182 |
183 | CRGB color = effects.ColorFromCurrentPalette(hue, 128);
184 |
185 | // Backface
186 | EdgePoint *e;
187 | for (i = 0; i < 12; i++)
188 | {
189 | e = edge + i;
190 | if (!e->visible) {
191 | effects.drawLine(screen[e->x].x, screen[e->x].y, screen[e->y].x, screen[e->y].y, color);
192 | }
193 | }
194 |
195 | color = effects.ColorFromCurrentPalette(hue, 255);
196 |
197 | // Frontface
198 | for (i = 0; i < 12; i++)
199 | {
200 | e = edge + i;
201 | if (e->visible)
202 | {
203 | effects.drawLine(screen[e->x].x, screen[e->x].y, screen[e->y].x, screen[e->y].y, color);
204 | }
205 | }
206 |
207 | step++;
208 | if (step == 8) {
209 | step = 0;
210 | hue++;
211 | }
212 |
213 | effects.ShowFrame();
214 |
215 | return 20;
216 | }
217 | };
218 |
219 | #endif
220 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternElectricMandala.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Portions of this code are adapted from "Funky Noise" by Stefan Petrick: https://github.com/StefanPetrick/FunkyNoise
6 | * Copyright (c) 2014 Stefan Petrick
7 | * http://www.stefan-petrick.de/wordpress_beta
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
10 | * this software and associated documentation files (the "Software"), to deal in
11 | * the Software without restriction, including without limitation the rights to
12 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13 | * the Software, and to permit persons to whom the Software is furnished to do so,
14 | * subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in all
17 | * copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 | */
26 |
27 | #ifndef PatternElectricMandala_H
28 |
29 | class PatternElectricMandala : public Drawable {
30 | private:
31 |
32 | // The coordinates for 16-bit noise spaces.
33 | #define NUM_LAYERS 1
34 |
35 | // used for the random based animations
36 | int16_t dx;
37 | int16_t dy;
38 | int16_t dz;
39 | int16_t dsx;
40 | int16_t dsy;
41 |
42 |
43 | unsigned int last_parameter_change_ms = 0;
44 |
45 | public:
46 | PatternElectricMandala() {
47 | name = (char *)"ElectricMandala";
48 | }
49 |
50 | void start() {
51 | // set to reasonable values to avoid a black out
52 | effects.noisesmoothing = 200;
53 |
54 | // just any free input pin
55 | //random16_add_entropy(analogRead(18));
56 |
57 | // fill coordinates with random values
58 | // set zoom levels
59 | effects.noise_x = random16();
60 | effects.noise_y = random16();
61 | effects.noise_z = random16();
62 | effects.noise_scale_x = 6000;
63 | effects.noise_scale_y = 6000;
64 |
65 | // for the random movement
66 | dx = random8();
67 | dy = random8();
68 | dz = random8();
69 | dsx = random8();
70 | dsy = random8();
71 | }
72 |
73 | unsigned int drawFrame() {
74 | #if FASTLED_VERSION >= 3001000
75 | // a new parameter set every 15 seconds
76 | if(millis() - last_parameter_change_ms > 15000) {
77 | last_parameter_change_ms = millis();
78 | //SetupRandomPalette3();
79 | dy = random16(500) - 250; // random16(2000) - 1000 is pretty fast but works fine, too
80 | dx = random16(500) - 250;
81 | dz = random16(500) - 250;
82 | effects.noise_scale_x = random16(10000) + 2000;
83 | effects.noise_scale_y = random16(10000) + 2000;
84 | }
85 | #endif
86 |
87 | effects.noise_y += dy;
88 | effects.noise_x += dx;
89 | effects.noise_z += dz;
90 |
91 | effects.FillNoise();
92 | ShowNoiseLayer(0, 1, 0);
93 |
94 | effects.Caleidoscope3();
95 | effects.Caleidoscope1();
96 |
97 | effects.ShowFrame();
98 |
99 | return 30;
100 | }
101 |
102 | // show just one layer
103 | void ShowNoiseLayer(byte layer, byte colorrepeat, byte colorshift) {
104 | for (uint16_t i = 0; i < VPANEL_W; i++) {
105 | for (uint16_t j = 0; j < VPANEL_H; j++) {
106 |
107 | uint8_t color = effects.noise[i][j];
108 |
109 | uint8_t bri = color;
110 |
111 | // assign a color depending on the actual palette
112 | CRGB pixel = ColorFromPalette(effects.currentPalette, colorrepeat * (color + colorshift), bri);
113 |
114 | effects.leds[XY16(i, j)] = pixel;
115 | }
116 | }
117 | }
118 | };
119 |
120 | #endif
121 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternFlock.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Portions of this code are adapted from "Flocking" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/
6 | * Copyright (c) 2014 Daniel Shiffman
7 | * http://www.shiffman.net
8 | *
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
10 | * this software and associated documentation files (the "Software"), to deal in
11 | * the Software without restriction, including without limitation the rights to
12 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13 | * the Software, and to permit persons to whom the Software is furnished to do so,
14 | * subject to the following conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be included in all
17 | * copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 | */
26 |
27 | // Flocking
28 | // Daniel Shiffman
29 | // The Nature of Code, Spring 2009
30 |
31 | // Demonstration of Craig Reynolds' "Flocking" behavior
32 | // See: http://www.red3d.com/cwr/
33 | // Rules: Cohesion, Separation, Alignment
34 |
35 | #ifndef PatternFlock_H
36 | #define PatternFlock_H
37 |
38 | class PatternFlock : public Drawable {
39 |
40 | private:
41 | unsigned long last_update_hue_ms = 0;
42 | unsigned long last_update_predator_ms = 0;
43 |
44 | public:
45 | PatternFlock() {
46 | name = (char *)"Flock";
47 | }
48 |
49 | static const int boidCount = VPANEL_W-1;
50 | Boid predator;
51 |
52 | PVector wind;
53 | byte hue = 0;
54 | bool predatorPresent = true;
55 |
56 | void start() {
57 | for (int i = 0; i < boidCount; i++) {
58 | boids[i] = Boid(15, 15);
59 | boids[i].maxspeed = 0.380;
60 | boids[i].maxforce = 0.015;
61 | }
62 |
63 | predatorPresent = random(0, 2) >= 1;
64 | if (predatorPresent) {
65 | predator = Boid(31, 31);
66 | predatorPresent = true;
67 | predator.maxspeed = 0.385;
68 | predator.maxforce = 0.020;
69 | predator.neighbordist = 16.0;
70 | predator.desiredseparation = 0.0;
71 | }
72 | }
73 |
74 | unsigned int drawFrame() {
75 | effects.DimAll(230); effects.ShowFrame();
76 |
77 | bool applyWind = random(0, 255) > 250;
78 | if (applyWind) {
79 | wind.x = Boid::randomf() * .015;
80 | wind.y = Boid::randomf() * .015;
81 | }
82 |
83 | CRGB color = effects.ColorFromCurrentPalette(hue);
84 |
85 | for (int i = 0; i < boidCount; i++) {
86 | Boid * boid = &boids[i];
87 |
88 | if (predatorPresent) {
89 | // flee from predator
90 | boid->repelForce(predator.location, 10);
91 | }
92 |
93 | boid->run(boids, boidCount);
94 | boid->wrapAroundBorders();
95 | PVector location = boid->location;
96 | // PVector velocity = boid->velocity;
97 | // backgroundLayer.drawLine(location.x, location.y, location.x - velocity.x, location.y - velocity.y, color);
98 | // effects.leds[XY16(location.x, location.y)] += color;
99 | effects.setPixel(location.x, location.y, color);
100 |
101 | if (applyWind) {
102 | boid->applyForce(wind);
103 | applyWind = false;
104 | }
105 | }
106 |
107 | if (predatorPresent) {
108 | predator.run(boids, boidCount);
109 | predator.wrapAroundBorders();
110 | color = effects.ColorFromCurrentPalette(hue + 128);
111 | PVector location = predator.location;
112 | // PVector velocity = predator.velocity;
113 | // backgroundLayer.drawLine(location.x, location.y, location.x - velocity.x, location.y - velocity.y, color);
114 | // effects.leds[XY16(location.x, location.y)] += color;
115 | effects.setPixel(location.x, location.y, color);
116 | }
117 |
118 | if (millis() - last_update_hue_ms > 200) {
119 | last_update_hue_ms = millis();
120 | hue++;
121 | }
122 |
123 | if (millis() - last_update_predator_ms > 30000) {
124 | last_update_predator_ms = millis();
125 | predatorPresent = !predatorPresent;
126 | }
127 |
128 | return 0;
129 | }
130 | };
131 |
132 | #endif
133 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternFlowField.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef PatternFlowField_H
24 |
25 | class PatternFlowField : public Drawable {
26 | public:
27 | PatternFlowField() {
28 | name = (char *)"FlowField";
29 | }
30 |
31 | uint16_t x;
32 | uint16_t y;
33 | uint16_t z;
34 |
35 | uint16_t speed = 1;
36 | uint16_t scale = 26;
37 |
38 | static const int count = 40;
39 |
40 | unsigned long last_update_hue_ms = 0;
41 | byte hue = 0;
42 |
43 | void start() {
44 | x = random16();
45 | y = random16();
46 | z = random16();
47 |
48 | for (int i = 0; i < count; i++) {
49 | boids[i] = Boid(random(VPANEL_W), 0);
50 | }
51 | }
52 |
53 | unsigned int drawFrame() {
54 | effects.DimAll(240);
55 |
56 | // CRGB color = effects.ColorFromCurrentPalette(hue);
57 |
58 | for (int i = 0; i < count; i++) {
59 | Boid * boid = &boids[i];
60 |
61 | int ioffset = scale * boid->location.x;
62 | int joffset = scale * boid->location.y;
63 |
64 | byte angle = inoise8(x + ioffset, y + joffset, z);
65 |
66 | boid->velocity.x = (float) sin8(angle) * 0.0078125 - 1.0;
67 | boid->velocity.y = -((float)cos8(angle) * 0.0078125 - 1.0);
68 | boid->update();
69 |
70 | effects.setPixel(boid->location.x, boid->location.y, effects.ColorFromCurrentPalette(angle + hue)); // color
71 |
72 | if (boid->location.x < 0 || boid->location.x >= VPANEL_W ||
73 | boid->location.y < 0 || boid->location.y >= VPANEL_H) {
74 | boid->location.x = random(VPANEL_W);
75 | boid->location.y = 0;
76 | }
77 | }
78 |
79 | if (millis() - last_update_hue_ms > 200) {
80 | last_update_hue_ms = millis();
81 | hue++;
82 | }
83 |
84 | x += speed;
85 | y += speed;
86 | z += speed;
87 |
88 | effects.ShowFrame();
89 |
90 | return 50;
91 | }
92 | };
93 |
94 | #endif
95 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternGreenScroll.hpp:
--------------------------------------------------------------------------------
1 | // Codetastic 2024
2 | // ChatGPT was used to create this.
3 | // It sucks.
4 |
5 | #ifndef PatternTheMatrix_H
6 | #define PatternTheMatrix_H
7 |
8 | // Function to generate a random greenish color for the digital rain
9 | CRGB generateRainColor() {
10 | return CHSV(96 + random(64), 255, 255); // Greenish colors
11 | }
12 |
13 |
14 | class PatternTheMatrix : public Drawable {
15 |
16 | public:
17 | PatternTheMatrix() {
18 | name = (char *)"The Matrix";
19 | }
20 |
21 |
22 | // Function to draw the digital rain effect
23 | void drawDigitalRain() {
24 | // Shift all the LEDs down by one row
25 | for (int x = 0; x < VPANEL_W ; x++) {
26 | for (int y = VPANEL_H - 1; y > 0; y--) {
27 | effects.leds[XY(x, y)] = effects.leds[XY(x, y - 1)];
28 | }
29 | // Add a new drop at the top of the column randomly
30 | if (random(10) > 7) { // Adjust the probability to control density of rain
31 | effects.leds[XY(x, 0)] = generateRainColor();
32 | } else {
33 | effects.leds[XY(x, 0)] = CRGB::Black;
34 | }
35 | }
36 | }
37 |
38 |
39 | void start()
40 | {
41 |
42 | };
43 |
44 | unsigned int drawFrame() {
45 |
46 | effects.DimAll(250);
47 |
48 | drawDigitalRain();
49 |
50 | effects.ShowFrame();
51 | return 0;
52 | }
53 | };
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternIncrementalDrift.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Aurora: https://github.com/pixelmatix/aurora
4 | * Copyright (c) 2014 Jason Coon
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | * this software and associated documentation files (the "Software"), to deal in
8 | * the Software without restriction, including without limitation the rights to
9 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | * the Software, and to permit persons to whom the Software is furnished to do so,
11 | * subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 |
24 | #ifndef PatternIncrementalDrift_H
25 | #define PatternIncrementalDrift_H
26 |
27 | class PatternIncrementalDrift : public Drawable {
28 | public:
29 | PatternIncrementalDrift() {
30 | name = (char *)"Incremental Drift";
31 | }
32 |
33 | unsigned int drawFrame() {
34 | //uint8_t dim = beatsin8(2, 230, 250);
35 | effects.DimAll(250);
36 |
37 | for (int i = 2; i <= VPANEL_W / 2; i++)
38 | {
39 | CRGB color = effects.ColorFromCurrentPalette((i - 2) * (240 / (VPANEL_W / 2)));
40 |
41 | uint8_t x = effects.beatcos8((17 - i) * 2, effects.getCenterX() - i, effects.getCenterX() + i);
42 | uint8_t y = beatsin8((17 - i) * 2, effects.getCenterY() - i, effects.getCenterY() + i);
43 |
44 | effects.setPixel(x, y, color);
45 | }
46 |
47 | effects.ShowFrame();
48 |
49 | return 0;
50 | }
51 | };
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternIncrementalDrift2.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Aurora: https://github.com/pixelmatix/aurora
4 | * Copyright (c) 2014 Jason Coon
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | * this software and associated documentation files (the "Software"), to deal in
8 | * the Software without restriction, including without limitation the rights to
9 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | * the Software, and to permit persons to whom the Software is furnished to do so,
11 | * subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 |
24 | #ifndef PatternIncrementalDrift2_H
25 | #define PatternIncrementalDrift2_H
26 |
27 | class PatternIncrementalDrift2 : public Drawable {
28 | public:
29 | PatternIncrementalDrift2() {
30 | name = (char *)"Incremental Drift Rose";
31 | }
32 |
33 | unsigned int drawFrame() {
34 | uint8_t dim = beatsin8(2, 170, 250);
35 | effects.DimAll(dim); effects.ShowFrame();
36 |
37 | for (int i = 2; i < VPANEL_H / 2; ++i)
38 | //for (uint8_t i = 0; i < 32; i++)
39 | {
40 | CRGB color;
41 |
42 | uint8_t x = 0;
43 | uint8_t y = 0;
44 |
45 | if (i < 16) {
46 | x = effects.beatcos8((i + 1) * 2, i, VPANEL_W - i);
47 | y = beatsin8((i + 1) * 2, i, VPANEL_H - i);
48 | color = effects.ColorFromCurrentPalette(i * 14);
49 | }
50 | else
51 | {
52 | x = beatsin8((32 - i) * 2, VPANEL_W - i, i + 1);
53 | y = effects.beatcos8((32 - i) * 2, VPANEL_H - i, i + 1);
54 | color = effects.ColorFromCurrentPalette((31 - i) * 14);
55 | }
56 |
57 | effects.setPixel(x, y, color);
58 | }
59 |
60 | return 0;
61 | }
62 | };
63 |
64 | #endif
65 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternInfinity.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef PatternInfinity_H
24 |
25 | class PatternInfinity : public Drawable {
26 | public:
27 | PatternInfinity() {
28 | name = (char *)"Infinity";
29 | }
30 |
31 | void start() {
32 | effects.ClearFrame();
33 | }
34 |
35 | unsigned int drawFrame() {
36 | // dim all pixels on the display slightly
37 | // to 250/255 (98%) of their current brightness
38 | //blur2d(effects.leds, VPANEL_W > 255 ? 255 : VPANEL_W, VPANEL_H > 255 ? 255 : VPANEL_H, 250);
39 | // effects.DimAll(250); effects.ShowFrame();
40 |
41 |
42 | // the EffectsLayer class has some sample oscillators
43 | // that move from 0 to 255 at different speeds
44 | effects.MoveOscillators();
45 |
46 | // the horizontal position of the head of the infinity sign
47 | // oscillates from 0 to the maximum horizontal and back
48 | int x = (VPANEL_W - 4) - effects.p[1];
49 |
50 | // the vertical position of the head oscillates
51 | // from 8 to 23 and back (hard-coded for a 32x32 matrix)
52 | int y = map8(sin8(effects.osci[3]), 8, VPANEL_H - 8);
53 |
54 | // the hue oscillates from 0 to 255, overflowing back to 0
55 | byte hue = sin8(effects.osci[5]);
56 |
57 | // draw a pixel at x,y using a color from the current palette
58 | effects.drawTriangle(x,y,x+1,y+1,x+2,y+2,effects.ColorFromCurrentPalette(hue));
59 | ////effects.setPixelFromPaletteIndex(x, y, hue);
60 |
61 | effects.ShowFrame();
62 | return 30;
63 | }
64 | };
65 |
66 | #endif
67 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternJuliaSetFractal.hpp:
--------------------------------------------------------------------------------
1 | #ifndef JuliaSet_H
2 | #define JuliaSet_H
3 |
4 | // Codetastic 2024
5 |
6 | #define USE_FLOATHACK // To boost float performance, comment if this doesn't work.
7 |
8 | // inspired by
9 | // https://en.wikipedia.org/wiki/Fast_inverse_square_root
10 | #ifdef USE_FLOATHACK
11 | // cast float as int32_t
12 | int32_t intfloat(float n){ return *(int32_t *)&n; }
13 | // cast int32_t as float
14 | float floatint(int32_t n){ return *(float *)&n; }
15 | // fast approx sqrt(x)
16 | float floatsqrt(float n){ return floatint(0x1fbb4000+(intfloat(n)>>1)); }
17 | // fast approx 1/x
18 | float floatinv(float n){ return floatint(0x7f000000-intfloat(n)); }
19 | // fast approx log2(x)
20 | float floatlog2(float n){ return (float)((intfloat(n)<<1)-0x7f000000)*5.9604645e-08f; }
21 | #else
22 | float floatinv(float n){ return 1.f/n;}
23 | float floatsqrt(float n){ return std::sqrt(n); }
24 | float floatlog2(float n){ return std::log2f(n); }
25 | #endif
26 |
27 | ////////////////////////////////////////
28 | // Escape time mandelbrot set function,
29 | // with arbitrary start point zx, zy
30 | // and arbitrary seed point ax, ay
31 | //
32 | // For julia set
33 | // zx = pos_x, zy = pos_y;
34 | // ax = seed_x, ay = seed_y;
35 | //
36 | // For mandelbrot set
37 | // zx = 0, zy = 0;
38 | // ax = pos_x, ay = pos_y;
39 | //
40 | const float bailOut = 4; // Escape radius
41 | const int32_t itmult = 1<<10; // Color speed
42 | //
43 | // https://en.wikipedia.org/wiki/Mandelbrot_set
44 | int32_t iteratefloat(float ax, float ay, float zx, float zy, uint16_t mxIT) {
45 | float zzl = 0;
46 | for (int it = 0; it=bailOut){
51 | if(it>0){
52 | // calculate smooth coloring
53 | float zza = floatlog2(zzl);
54 | float zzb = floatlog2(zzx+zzy);
55 | float zzc = floatlog2(bailOut);
56 | float zzd = (zzc-zza)*floatinv(zzb-zza);
57 | return it*itmult+zzd*itmult;
58 | }
59 | };
60 | // z -> z*z + c
61 | zy = 2.f*zx*zy+ay;
62 | zx = zzx-zzy+ax;
63 | zzl = zzx+zzy;
64 | }
65 | return 0;
66 | }
67 |
68 | class PatternJuliaSet : public Drawable {
69 |
70 | private:
71 |
72 | float sint[256]; // precalculated sin table, for performance reasons
73 |
74 | public:
75 | PatternJuliaSet() {
76 | name = (char *)"Julia Set";
77 | }
78 |
79 | void start() {
80 |
81 | for(int i=0;i<256;i++){
82 | sint[i] = sinf(i/256.f*2.f*PI);
83 | }
84 | }
85 |
86 |
87 | // Palette color taken from:
88 | // https://editor.p5js.org/Kouzerumatsukite/sketches/DwTiq9D01
89 | // color palette originally made by piano_miles, written in p5js
90 | // hsv2rgb(IT, cos(4096*it)/2+0.5, 1-sin(2048*it)/2-0.5)
91 | void drawPixelPalette(int x, int y, uint32_t m){
92 | float r = 0.f, g = 0.f, b = 0.f;
93 | if(m){
94 | char n = m>> 4 ;
95 | float l =abs(sint[m>> 2&255] )*255.f ;
96 | float s = (sint[m &255]+ 1.f)*0.5f ;
97 | r = (max(min(sint[n &255]+0.5f,1.f),0.f)*s+(1-s))*l;
98 | g = (max(min(sint[n+ 85&255]+0.5f,1.f),0.f)*s+(1-s))*l;
99 | b = (max(min(sint[n+170&255]+0.5f,1.f),0.f)*s+(1-s))*l;
100 | }
101 | effects.setPixel(x,y,CRGB(r,g,b));
102 |
103 | }
104 |
105 | unsigned int drawFrame() {
106 | uint32_t lastMicros = micros();
107 | double t = (double)lastMicros/8000000;
108 | double k = sin(t*3.212/2)*sin(t*3.212/2)/16+1;
109 | float cosk = (k-cos(t))/2;
110 | float xoff = (cos(t)*cosk+k/2-0.25);
111 | float yoff = (sin(t)*cosk );
112 | for(uint8_t y=0;y= VPANEL_W) {
55 | dir = -dir;
56 | }
57 |
58 | if (count <= 0) {
59 | if (flip == 0)
60 | flip = VPANEL_W-1;
61 | else
62 | flip = 0;
63 | }
64 |
65 | generation++;
66 |
67 | // show it ffs!
68 | effects.ShowFrame();
69 | return 60;
70 | }
71 | };
72 |
73 | #endif
74 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternPendulumWave.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Inspired by and based on a loading animation for Prismata by Lunarch Studios:
4 | * http://www.reddit.com/r/gifs/comments/2on8si/connecting_to_server_so_mesmerizing/cmow0sz
5 | *
6 | * Lunarch Studios Inc. hereby publishes the Actionscript 3 source code pasted in this
7 | * comment under the Creative Commons CC0 1.0 Universal Public Domain Dedication.
8 | * Lunarch Studios Inc. waives all rights to the work worldwide under copyright law,
9 | * including all related and neighboring rights, to the extent allowed by law.
10 | * You can copy, modify, distribute and perform the work, even for commercial purposes,
11 | * all without asking permission.
12 | *
13 | * Aurora: https://github.com/pixelmatix/aurora
14 | * Copyright (c) 2014 Jason Coon
15 | *
16 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
17 | * this software and associated documentation files (the "Software"), to deal in
18 | * the Software without restriction, including without limitation the rights to
19 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
20 | * the Software, and to permit persons to whom the Software is furnished to do so,
21 | * subject to the following conditions:
22 | *
23 | * The above copyright notice and this permission notice shall be included in all
24 | * copies or substantial portions of the Software.
25 | *
26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
28 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
29 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
30 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | #ifndef PatternPendulumWave_H
35 | #define PatternPendulumWave_H
36 |
37 | #define WAVE_BPM 25
38 | #define AMP_BPM 2
39 | #define SKEW_BPM 4
40 | #define WAVE_TIMEMINSKEW VPANEL_W/8
41 | #define WAVE_TIMEMAXSKEW effects.getCenterX()
42 |
43 | class PatternPendulumWave : public Drawable {
44 | public:
45 | PatternPendulumWave() {
46 | name = (char *)"Pendulum Wave";
47 | }
48 |
49 | unsigned int drawFrame()
50 | {
51 | effects.DimAll(192);
52 |
53 | for (int x = 0; x < VPANEL_W; ++x)
54 | {
55 | uint16_t amp = beatsin16(AMP_BPM, VPANEL_H/8, VPANEL_H-1);
56 | uint16_t offset = (VPANEL_H - beatsin16(AMP_BPM, 0, VPANEL_H))/2;
57 |
58 | uint8_t y = beatsin16(WAVE_BPM, 0, amp, x*beatsin16(SKEW_BPM, WAVE_TIMEMINSKEW, WAVE_TIMEMAXSKEW)) + offset;
59 |
60 | effects.setPixel(x, y, effects.ColorFromCurrentPalette(x * 7));
61 | }
62 | effects.ShowFrame();
63 | return 20;
64 | }
65 | };
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternPlasma.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Portions of this code are adapted from LedEffects Plasma by Robert Atkins: https://bitbucket.org/ratkins/ledeffects/src/26ed3c51912af6fac5f1304629c7b4ab7ac8ca4b/Plasma.cpp?at=default
6 | * Copyright (c) 2013 Robert Atkins
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
9 | * this software and associated documentation files (the "Software"), to deal in
10 | * the Software without restriction, including without limitation the rights to
11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12 | * the Software, and to permit persons to whom the Software is furnished to do so,
13 | * subject to the following conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be included in all
16 | * copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 | */
25 |
26 | #ifndef PatternPlasma_H
27 | #define PatternPlasma_H
28 |
29 | class PatternPlasma : public Drawable {
30 | private:
31 | int time = 0;
32 | int cycles = 0;
33 |
34 | public:
35 | PatternPlasma() {
36 | name = (char *)"Plasma";
37 | }
38 |
39 | unsigned int drawFrame() {
40 | for (int x = 0; x < VPANEL_W; x++) {
41 | for (int y = 0; y < VPANEL_H; y++) {
42 | int16_t v = 0;
43 | uint8_t wibble = sin8(time);
44 | v += sin16(x * wibble * 6 + time);
45 | v += cos16(y * (128 - wibble) * 6 + time);
46 | v += sin16(y * x * cos8(-time) / 8);
47 |
48 | effects.setPixelFromPaletteIndex(x, y, (v >> 8) + 127);
49 | }
50 | }
51 |
52 | time += 1;
53 | cycles++;
54 |
55 | if (cycles >= 2048) {
56 | time = 0;
57 | cycles = 0;
58 | }
59 |
60 | effects.ShowFrame();
61 |
62 | return 30;
63 | }
64 | };
65 |
66 | #endif
67 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternRadar.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef PatternRadar_H
24 |
25 | class PatternRadar : public Drawable {
26 | private:
27 | byte theta = 0;
28 | byte hueoffset = 0;
29 | unsigned long last_update_hue_ms = 0;
30 |
31 | public:
32 | PatternRadar() {
33 | name = (char *)"Radar";
34 | }
35 |
36 | unsigned int drawFrame() {
37 | effects.DimAll(254); effects.ShowFrame();
38 |
39 | for (int offset = 0; offset < effects.getCenterX(); offset++) {
40 | byte hue = 255 - (offset * 16 + hueoffset);
41 | CRGB color = effects.ColorFromCurrentPalette(hue);
42 | uint8_t x = effects.mapcos8(theta, offset, (VPANEL_W - 1) - offset);
43 | uint8_t y = effects.mapsin8(theta, offset, (VPANEL_H - 1) - offset);
44 | uint16_t xy = XY16(x, y);
45 | effects.leds[xy] = color;
46 |
47 | if (millis() - last_update_hue_ms > 25) {
48 | last_update_hue_ms = millis();
49 | theta += 2;
50 | hueoffset += 1;
51 | }
52 | }
53 |
54 | return 0;
55 | }
56 | };
57 |
58 | #endif
59 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternRain.hpp:
--------------------------------------------------------------------------------
1 | #ifndef PatternRain_H
2 | #define PatternRain_H
3 |
4 | // Codetastic 2024
5 |
6 | struct rainDrop {
7 | uint8_t x;
8 | uint8_t y;
9 | CRGB colour;
10 | };
11 |
12 | #define MAX_RAINDROPS 128
13 |
14 | class PatternRain : public Drawable {
15 |
16 | public:
17 | PatternRain()
18 | {
19 | name = (char *)"PatternRain";
20 | }
21 |
22 | void start() {
23 |
24 | buffer = (uint16_t *) malloc(((VPANEL_W*VPANEL_H)+1)*sizeof(uint16_t)); // always alloc an extra amount for XY
25 | }
26 |
27 | void stop() {
28 |
29 | free(buffer);
30 |
31 | }
32 |
33 |
34 | unsigned int drawFrame()
35 | {
36 | rain(32, 255, 224, 240, CRGB::Green);
37 |
38 | effects.ShowFrame();
39 |
40 | return 45; // 1000/45 frames per secton
41 |
42 | }
43 |
44 |
45 |
46 | private:
47 |
48 | struct rainDrop rainDrops[MAX_RAINDROPS];
49 | int rainDropPos = 0;
50 |
51 | uint16_t* buffer = NULL; // buffer of number
52 |
53 | void rain(byte backgroundDepth, byte maxBrightness, byte spawnFreq, byte tailLength, CRGB rainColor)
54 | {
55 | CRGBPalette16 rain_p( CRGB::Black, rainColor );
56 |
57 | // Dim routine
58 | for (int16_t i = 0; i < VPANEL_W; i++) {
59 | for (int16_t j = 0; j < VPANEL_H; j++) {
60 | uint16_t xy = XY16(i, j);
61 | effects.leds[xy].nscale8(tailLength);
62 | }
63 | }
64 |
65 | // Genrate a new raindrop if the randomness says we should
66 | if (random(255) < spawnFreq) {
67 |
68 | // Find a spare raindrop slot
69 | for (int d = 0; d < MAX_RAINDROPS; d++) {
70 |
71 | // This raindrop is done with, it has... dropped
72 | if (rainDrops[d].y >= VPANEL_H ) // not currently in use
73 | {
74 | rainDrops[d].colour = ColorFromPalette(rain_p, random(backgroundDepth, maxBrightness));
75 | rainDrops[d].x = random(VPANEL_W-1);
76 | rainDrops[d].y = 0;
77 |
78 | break; // exit until next time.
79 | }
80 | }
81 | } // end random spawn
82 |
83 | // Iterate through all the rainDrops, draw the drop pixel on the layer
84 | for (int d = 0; d < MAX_RAINDROPS; d++) {
85 | effects.setPixel(rainDrops[d].x, rainDrops[d].y++, rainDrops[d].colour);
86 | }
87 |
88 | }
89 |
90 |
91 | };
92 |
93 | #endif
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternSimplexNoise.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Portions of this code are adapted from FastLED Fire2012 example by Mark Kriegsman: https://github.com/FastLED/FastLED/blob/master/examples/Noise/Noise.ino
6 | * Copyright (c) 2013 FastLED
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
9 | * this software and associated documentation files (the "Software"), to deal in
10 | * the Software without restriction, including without limitation the rights to
11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12 | * the Software, and to permit persons to whom the Software is furnished to do so,
13 | * subject to the following conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be included in all
16 | * copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 | */
25 |
26 | #ifndef PatternSimplexNoise_H
27 | #define PatternSimplexNoise_H
28 |
29 | class PatternSimplexNoise : public Drawable {
30 |
31 | private:
32 |
33 | unsigned int last_update_ms = 0;
34 | public:
35 | PatternSimplexNoise() {
36 | name = (char *)"Noise";
37 | }
38 |
39 | void start() {
40 | // Initialize our coordinates to some random values
41 | effects.noise_x = random16();
42 | effects.noise_y = random16();
43 | effects.noise_z = random16();
44 | }
45 |
46 | unsigned int drawFrame() {
47 | #if FASTLED_VERSION >= 3001000
48 | // a new parameter set every 15 seconds
49 | if(millis() - last_update_ms > 15000) {
50 | last_update_ms = millis();
51 | effects.noise_x = random16();
52 | effects.noise_y = random16();
53 | effects.noise_z = random16();
54 | }
55 | #endif
56 |
57 | uint32_t speed = 100;
58 |
59 | effects.FillNoise();
60 | ShowNoiseLayer(0, 1, 0);
61 |
62 | // noise_x += speed;
63 | effects.noise_y += speed;
64 | effects.noise_z += speed;
65 |
66 | effects.ShowFrame();
67 |
68 | return 30;
69 | }
70 |
71 | // show just one layer
72 | void ShowNoiseLayer(byte layer, byte colorrepeat, byte colorshift) {
73 | for (uint16_t i = 0; i < VPANEL_W; i++) {
74 | for (uint16_t j = 0; j < VPANEL_H; j++) {
75 | uint8_t pixel = effects.noise[i][j];
76 |
77 | // assign a color depending on the actual palette
78 | effects.leds[XY16(i, j)] = effects.ColorFromCurrentPalette(colorrepeat * (pixel + colorshift), pixel);
79 | }
80 | }
81 | }
82 | };
83 |
84 | #endif
85 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternSnake.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Portions of this code are adapted from LedEffects Snake by Robert Atkins: https://bitbucket.org/ratkins/ledeffects/src/26ed3c51912af6fac5f1304629c7b4ab7ac8ca4b/Snake.cpp?at=default
6 | * Copyright (c) 2013 Robert Atkins
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
9 | * this software and associated documentation files (the "Software"), to deal in
10 | * the Software without restriction, including without limitation the rights to
11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12 | * the Software, and to permit persons to whom the Software is furnished to do so,
13 | * subject to the following conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be included in all
16 | * copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 | */
25 |
26 | #ifndef PatternSnake_H
27 | #define PatternSnake_H
28 |
29 | class PatternSnake : public Drawable {
30 | private:
31 | static const byte SNAKE_LENGTH = 8;
32 |
33 | CRGB colors[SNAKE_LENGTH];
34 | uint8_t initialHue;
35 |
36 | enum Direction {
37 | UP, DOWN, LEFT, RIGHT
38 | };
39 |
40 | struct Pixel {
41 | uint8_t x;
42 | uint8_t y;
43 | };
44 |
45 | struct Snake {
46 | Pixel pixels[SNAKE_LENGTH];
47 |
48 | Direction direction;
49 |
50 | void newDirection() {
51 | switch (direction) {
52 | case UP:
53 | case DOWN:
54 | direction = random(0, 2) == 1 ? RIGHT : LEFT;
55 | break;
56 |
57 | case LEFT:
58 | case RIGHT:
59 | direction = random(0, 2) == 1 ? DOWN : UP;
60 |
61 | default:
62 | break;
63 | }
64 | }
65 |
66 | void shuffleDown() {
67 | for (byte i = SNAKE_LENGTH - 1; i > 0; i--) {
68 | pixels[i] = pixels[i - 1];
69 | }
70 | }
71 |
72 | void reset() {
73 | direction = UP;
74 | for (int i = 0; i < SNAKE_LENGTH; i++) {
75 | pixels[i].x = 0;
76 | pixels[i].y = 0;
77 | }
78 | }
79 |
80 | void move() {
81 | switch (direction) {
82 | case UP:
83 | pixels[0].y = (pixels[0].y + 1) % VPANEL_H;
84 | break;
85 | case LEFT:
86 | pixels[0].x = (pixels[0].x + 1) % VPANEL_W;
87 | break;
88 | case DOWN:
89 | pixels[0].y = pixels[0].y == 0 ? VPANEL_H - 1 : pixels[0].y - 1;
90 | break;
91 | case RIGHT:
92 | pixels[0].x = pixels[0].x == 0 ? VPANEL_W - 1 : pixels[0].x - 1;
93 | break;
94 | }
95 | }
96 |
97 | void draw(CRGB colors[SNAKE_LENGTH]) {
98 | for (byte i = 0; i < SNAKE_LENGTH; i++) {
99 | effects.leds[XY16(pixels[i].x, pixels[i].y)] = colors[i] %= (255 - i * (255 / SNAKE_LENGTH));
100 | }
101 | }
102 | };
103 |
104 | static const int snakeCount = 6;
105 | Snake snakes[snakeCount];
106 |
107 | public:
108 | PatternSnake() {
109 | name = (char *)"Snake";
110 | for (int i = 0; i < snakeCount; i++) {
111 | Snake* snake = &snakes[i];
112 | snake->reset();
113 | }
114 | }
115 |
116 | void start()
117 | {
118 | effects.ClearFrame();
119 | }
120 |
121 | unsigned int drawFrame() {
122 |
123 |
124 | fill_palette(colors, SNAKE_LENGTH, initialHue++, 5, effects.currentPalette, 255, LINEARBLEND);
125 |
126 | for (int i = 0; i < snakeCount; i++) {
127 | Snake* snake = &snakes[i];
128 |
129 | snake->shuffleDown();
130 |
131 | if (random(10) > 7) {
132 | snake->newDirection();
133 | }
134 |
135 | snake->move();
136 | snake->draw(colors);
137 | }
138 |
139 | effects.ShowFrame();
140 |
141 | return 30;
142 | }
143 | };
144 |
145 | #endif
146 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternSpin.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef PatternSpin_H
24 |
25 |
26 |
27 | class PatternSpin : public Drawable {
28 | public:
29 | PatternSpin() {
30 | name = (char *)"Spin";
31 | }
32 |
33 | float degrees = 0;
34 | float radius = 16;
35 |
36 | float speedStart = 1;
37 | float velocityStart = 0.6;
38 |
39 | float maxSpeed = 30;
40 |
41 | float speed = speedStart;
42 | float velocity = velocityStart;
43 |
44 | void start() {
45 | speed = speedStart;
46 | velocity = velocityStart;
47 | degrees = 0;
48 | }
49 |
50 | unsigned int drawFrame() {
51 |
52 |
53 | CRGB color = effects.ColorFromCurrentPalette(speed * 8);
54 |
55 | // start position
56 | int x;
57 | int y;
58 |
59 | // target position
60 | float targetDegrees = degrees + speed;
61 | float targetRadians = radians(targetDegrees);
62 | int targetX = (int) (effects.getCenterX() + radius * cos(targetRadians));
63 | int targetY = (int) (effects.getCenterY() - radius * sin(targetRadians));
64 |
65 | float tempDegrees = degrees;
66 |
67 | for (int i =0; i < 16; i++)
68 | {
69 | float radians = radians(tempDegrees);
70 | x = (int) (effects.getCenterX() + radius * cos(radians));
71 | y = (int) (effects.getCenterY() - radius * sin(radians));
72 |
73 | effects.setPixel(x, y, color);
74 | effects.setPixel(y, x, color);
75 |
76 | tempDegrees += 1;
77 | if (tempDegrees >= 360)
78 | tempDegrees = 0;
79 |
80 | }
81 |
82 |
83 | degrees += speed;
84 |
85 | // add velocity to the particle each pass around the accelerator
86 | if (degrees >= 360) {
87 | degrees = 0;
88 | speed += velocity;
89 | if (speed <= speedStart) {
90 | speed = speedStart;
91 | velocity *= -1;
92 | }
93 | else if (speed > maxSpeed){
94 | speed = maxSpeed - velocity;
95 | velocity *= -1;
96 | }
97 | }
98 |
99 | effects.ShowFrame();
100 |
101 | return 0;
102 | }
103 | };
104 |
105 | #endif
106 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternSpiral.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Portions of this code are adapted from "Funky Clouds" by Stefan Petrick:
3 | * https://gist.github.com/anonymous/876f908333cd95315c35
4 | *
5 | * Copyright (c) 2014 Stefan Petrick
6 | * http://www.stefan-petrick.de/wordpress_beta
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
9 | * this software and associated documentation files (the "Software"), to deal in
10 | * the Software without restriction, including without limitation the rights to
11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12 | * the Software, and to permit persons to whom the Software is furnished to do so,
13 | * subject to the following conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be included in all
16 | * copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 | */
25 |
26 | #ifndef PatternSpiral_H
27 | #define PatternSpiral_H
28 |
29 | class PatternSpiral : public Drawable {
30 | private:
31 | // Timer stuff (Oscillators)
32 | struct timer {
33 | unsigned long takt;
34 | unsigned long lastMillis;
35 | unsigned long count;
36 | int delta;
37 | byte up;
38 | byte down;
39 | };
40 | timer multiTimer[5];
41 |
42 | int timers = sizeof(multiTimer) / sizeof(multiTimer[0]);
43 |
44 | // counts all variables with different speeds linear up and down
45 | void UpdateTimers()
46 | {
47 | unsigned long now = millis();
48 | for (int i = 0; i < timers; i++)
49 | {
50 | while (now - multiTimer[i].lastMillis >= multiTimer[i].takt)
51 | {
52 | multiTimer[i].lastMillis += multiTimer[i].takt;
53 | multiTimer[i].count = multiTimer[i].count + multiTimer[i].delta;
54 | if ((multiTimer[i].count == multiTimer[i].up) || (multiTimer[i].count == multiTimer[i].down))
55 | {
56 | multiTimer[i].delta = -multiTimer[i].delta;
57 | }
58 | }
59 | }
60 | }
61 |
62 | public:
63 | PatternSpiral() {
64 | name = (char *)"Spiral";
65 | }
66 |
67 | void start() {
68 | // set all counting directions positive for the beginning
69 | for (int i = 0; i < timers; i++) multiTimer[i].delta = 1;
70 |
71 | // set range (up/down), speed (takt=ms between steps) and starting point of all oscillators
72 |
73 | unsigned long now = millis();
74 |
75 | multiTimer[0].lastMillis = now;
76 | multiTimer[0].takt = 42; //x1
77 | multiTimer[0].up = VPANEL_W - 1;
78 | multiTimer[0].down = 0;
79 | multiTimer[0].count = 0;
80 |
81 | multiTimer[1].lastMillis = now;
82 | multiTimer[1].takt = 55; //y1
83 | multiTimer[1].up = VPANEL_H - 1;
84 | multiTimer[1].down = 0;
85 | multiTimer[1].count = 0;
86 |
87 | multiTimer[2].lastMillis = now;
88 | multiTimer[2].takt = 3; //color
89 | multiTimer[2].up = 255;
90 | multiTimer[2].down = 0;
91 | multiTimer[2].count = 0;
92 |
93 | multiTimer[3].lastMillis = now;
94 | multiTimer[3].takt = 71; //x2
95 | multiTimer[3].up = VPANEL_W - 1;
96 | multiTimer[3].down = 0;
97 | multiTimer[3].count = 0;
98 |
99 | multiTimer[4].lastMillis = now;
100 | multiTimer[4].takt = 89; //y2
101 | multiTimer[4].up = VPANEL_H - 1;
102 | multiTimer[4].down = 0;
103 | multiTimer[4].count = 0;
104 | }
105 |
106 | unsigned int drawFrame() {
107 | // manage the Oscillators
108 | UpdateTimers();
109 |
110 | // draw just a line defined by 5 oscillators
111 | effects.BresenhamLine(
112 | multiTimer[3].count, // x1
113 | multiTimer[4].count, // y1
114 | multiTimer[0].count, // x2
115 | multiTimer[1].count, // y2
116 | multiTimer[2].count); // color
117 |
118 | // manipulate the screen buffer
119 | // with fixed parameters (could be oscillators too)
120 | // Params: center x, y, radius, scale color down
121 | // --> NOTE: Affects always a SQUARE with an odd length
122 | // effects.SpiralStream(15, 15, 10, 128);
123 |
124 | effects.SpiralStream(31, 15, 64, 128); // for 64 pixel wide matrix!
125 | // effects.SpiralStream(47, 15, 10, 128); // for 64 pixel wide matrix!
126 |
127 | // why not several times?!
128 | // effects.SpiralStream(16, 6, 6, 128);
129 | // effects.SpiralStream(10, 24, 10, 128);
130 |
131 | // increase the contrast
132 | effects.DimAll(250); effects.ShowFrame();
133 |
134 | return 0;
135 | }
136 | };
137 |
138 | #endif
139 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternSpiro.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef PatternSpiro_H
24 |
25 | class PatternSpiro : public Drawable {
26 | private:
27 | byte theta1 = 0;
28 | byte theta2 = 0;
29 | byte hueoffset = 0;
30 |
31 | uint8_t radiusx = VPANEL_W / 4;
32 | uint8_t radiusy = VPANEL_H / 4;
33 | uint8_t minx = effects.getCenterX() - radiusx;
34 | uint8_t maxx = effects.getCenterX() + radiusx + 1;
35 | uint8_t miny = effects.getCenterY() - radiusy;
36 | uint8_t maxy = effects.getCenterY() + radiusy + 1;
37 |
38 | uint8_t spirocount = 64;
39 | uint8_t spirooffset = 256 / spirocount;
40 | boolean spiroincrement = true;
41 |
42 | boolean handledChange = false;
43 |
44 | unsigned long last_update_theta1_ms = 0;
45 | unsigned long last_update_hue_ms = 0;
46 | unsigned long last_update_frame_ms = 0;
47 |
48 | public:
49 | PatternSpiro() {
50 | name = (char *)"Spiro";
51 | }
52 |
53 | void start(){
54 | effects.ClearFrame();
55 | };
56 |
57 | unsigned int drawFrame() {
58 | blur2d(effects.leds, VPANEL_W > 255 ? 255 : VPANEL_W, VPANEL_H > 255 ? 255 : VPANEL_H, 64);
59 |
60 | boolean change = false;
61 |
62 | for (int i = 0; i < spirocount; i++) {
63 | uint8_t x = effects.mapsin8(theta1 + i * spirooffset, minx, maxx);
64 | uint8_t y = effects.mapcos8(theta1 + i * spirooffset, miny, maxy);
65 |
66 | uint8_t x2 = effects.mapsin8(theta2 + i * spirooffset, x - radiusx, x + radiusx);
67 | uint8_t y2 = effects.mapcos8(theta2 + i * spirooffset, y - radiusy, y + radiusy);
68 |
69 | CRGB color = effects.ColorFromCurrentPalette(hueoffset + i * spirooffset, 128);
70 | effects.leds[XY16(x2, y2)] += color;
71 |
72 | if((x2 == effects.getCenterX() && y2 == effects.getCenterY()) ||
73 | (x2 == effects.getCenterX() && y2 == effects.getCenterY())) change = true;
74 | }
75 |
76 | theta2 += 1;
77 |
78 | if (millis() - last_update_theta1_ms > 25) {
79 | last_update_theta1_ms = millis();
80 | theta1 += 1;
81 | }
82 |
83 | if (millis() - last_update_frame_ms > 100) {
84 | last_update_frame_ms = millis();
85 |
86 | if (change && !handledChange) {
87 | handledChange = true;
88 |
89 | if (spirocount >= VPANEL_W || spirocount == 1) spiroincrement = !spiroincrement;
90 |
91 | if (spiroincrement) {
92 | if(spirocount >= 4)
93 | spirocount *= 2;
94 | else
95 | spirocount += 1;
96 | }
97 | else {
98 | if(spirocount > 4)
99 | spirocount /= 2;
100 | else
101 | spirocount -= 1;
102 | }
103 |
104 | spirooffset = 256 / spirocount;
105 | }
106 |
107 | if(!change) handledChange = false;
108 | }
109 |
110 | if (millis() - last_update_hue_ms > 33) {
111 | last_update_hue_ms = millis();
112 | hueoffset += 1;
113 | }
114 |
115 | effects.ShowFrame();
116 | return 0;
117 | }
118 | };
119 |
120 | #endif
121 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternStarfield.hpp:
--------------------------------------------------------------------------------
1 | #ifndef PatternStarfield_H
2 | #define PatternStarfield_H
3 |
4 | struct Star
5 | {
6 | Star() {
7 | x = y = z = 0;
8 | colour = CRGB::White;
9 | }
10 |
11 | float x;
12 | float y;
13 | float z;
14 | CRGB colour;
15 | };
16 |
17 |
18 | // Based on https://github.com/sinoia/oled-starfield/blob/master/src/starfield.cpp
19 | class PatternStarfield : public Drawable {
20 |
21 | private:
22 |
23 | const int starCount = 100; // number of stars in the star field
24 | const int maxDepth = 32; // maximum distance away for a star
25 |
26 | // the star field - starCount stars represented as x, y and z co-ordinates
27 | // https://www.cplusplus.com/doc/tutorial/dynamic/
28 | Star * stars;
29 | //CRGBPalette16 currentPalette;
30 |
31 | unsigned int drawFrame() { // aka drawStars
32 |
33 | // Dim routine
34 |
35 | for (int16_t i = 0; i < VPANEL_W; i++) {
36 | for (int16_t j = 0; j < VPANEL_H; j++) {
37 |
38 | uint16_t xy = XY16(i, j);
39 | effects.leds[xy].nscale8(250);
40 | }
41 | }
42 |
43 | int origin_x = VPANEL_W / 2;
44 | int origin_y = VPANEL_H / 2;
45 |
46 | // Iterate through the stars reducing the z co-ordinate in order to move the
47 | // star closer.
48 | for (int i = 0; i < starCount; ++i) {
49 | stars[i].z -= 0.1;
50 | // if the star has moved past the screen (z < 0) reposition it far away
51 | // with random x and y positions.
52 | if (stars[i].z <= 0)
53 | {
54 | stars[i].x = getRandom(-25, 25);
55 | stars[i].y = getRandom(-25, 25);
56 | stars[i].z = maxDepth;
57 | }
58 |
59 | // Convert the 3D coordinates to 2D using perspective projection.
60 | float k = VPANEL_W / stars[i].z;
61 | int x = static_cast(stars[i].x * k + origin_x);
62 | int y = static_cast(stars[i].y * k + origin_y);
63 |
64 | // Draw the star (if it is visible in the screen).
65 | // Distant stars are smaller than closer stars.
66 | if ((0 <= x and x < VPANEL_H)
67 | and (0 <= y and y < VPANEL_H)) {
68 |
69 | CRGB tmp = stars[i].colour;
70 | //CRGB tmp = CRGB::White;
71 | byte scale = 255 -(stars[i].z*7);
72 | tmp.nscale8(scale);
73 |
74 | effects.setPixel(x,y, CRGB(tmp.r,tmp.g,tmp.b));
75 | }
76 | else
77 | {
78 | stars[i].z = -1; // set to -1 so it gets re-popualted
79 | }
80 | }
81 |
82 | effects.ShowFrame();
83 |
84 | return 5;
85 | }
86 |
87 | int getRandom(int lower, int upper) {
88 | /* Generate and return a random number between lower and upper bound */
89 | return lower + static_cast(rand() % (upper - lower + 1));
90 | }
91 |
92 | /*
93 | CRGB ColorFromCurrentPalette(uint8_t index = 0, uint8_t brightness = 255, TBlendType blendType = LINEARBLEND) {
94 | return ColorFromPalette(currentPalette, index, brightness, blendType);
95 | }
96 | */
97 |
98 | public:
99 | PatternStarfield()
100 | {
101 | name = (char *)"PatternStarfield";
102 | }
103 |
104 | void start() {
105 |
106 | //currentPalette = RainbowColors_p;
107 | //currentPalette = CloudColors_p;
108 |
109 | // Allocate memory
110 | stars = new Star[starCount];
111 |
112 | // Initialise the star field with random stars
113 | for (int i = 0; i < starCount; i++) {
114 | stars[i].x = getRandom(-25, 25);
115 | stars[i].y = getRandom(-25, 25);
116 | stars[i].z = getRandom(0, maxDepth);
117 | //stars[i].colour = ColorFromCurrentPalette(random(0, 128));
118 | stars[i].colour = effects.ColorFromCurrentPalette(random(0, 128));
119 | }
120 | } // end start
121 |
122 | void stop() {
123 | delete[] stars;
124 | }
125 |
126 |
127 |
128 | };
129 |
130 | #endif
131 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternTest.hpp:
--------------------------------------------------------------------------------
1 |
2 | #ifndef PatternTest_H
3 | #define PatternTest_H
4 |
5 | class PatternTest : public Drawable {
6 | private:
7 |
8 | public:
9 | PatternTest() {
10 | name = (char *)"Test Pattern";
11 | }
12 |
13 | unsigned int drawFrame() {
14 |
15 | matrix->fillScreen(matrix->color565(128, 0, 0));
16 | return 1000;
17 | }
18 | };
19 |
20 | #endif
21 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/PatternWave.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef PatternWave_H
24 | #define PatternWave_H
25 |
26 | class PatternWave : public Drawable {
27 | private:
28 | byte thetaUpdate = 0;
29 | byte thetaUpdateFrequency = 0;
30 | byte theta = 0;
31 |
32 | byte hueUpdate = 0;
33 | byte hueUpdateFrequency = 0;
34 | byte hue = 0;
35 |
36 | byte rotation = 0;
37 |
38 | uint8_t scale = 256 / VPANEL_W;
39 |
40 | uint8_t maxX = VPANEL_W - 1;
41 | uint8_t maxY = VPANEL_H - 1;
42 |
43 | uint8_t waveCount = 1;
44 |
45 | public:
46 | PatternWave() {
47 | name = (char *)"Wave";
48 | }
49 |
50 | void start() {
51 | rotation = random(0, 4);
52 | waveCount = random(1, 3);
53 |
54 | }
55 |
56 | unsigned int drawFrame() {
57 | int n = 0;
58 |
59 | switch (rotation) {
60 | case 0:
61 | for (int x = 0; x < VPANEL_W; x++) {
62 | n = quadwave8(x * 2 + theta) / scale;
63 | effects.setPixel(x, n, effects.ColorFromCurrentPalette(x + hue));
64 | if (waveCount == 2)
65 | effects.setPixel(x, maxY - n, effects.ColorFromCurrentPalette(x + hue));
66 | }
67 | break;
68 |
69 | case 1:
70 | for (int y = 0; y < VPANEL_H; y++) {
71 | n = quadwave8(y * 2 + theta) / scale;
72 | effects.setPixel(n, y, effects.ColorFromCurrentPalette(y + hue));
73 | if (waveCount == 2)
74 | effects.setPixel(maxX - n, y, effects.ColorFromCurrentPalette(y + hue));
75 | }
76 | break;
77 |
78 | case 2:
79 | for (int x = 0; x < VPANEL_W; x++) {
80 | n = quadwave8(x * 2 - theta) / scale;
81 | effects.setPixel(x, n, effects.ColorFromCurrentPalette(x + hue));
82 | if (waveCount == 2)
83 | effects.setPixel(x, maxY - n, effects.ColorFromCurrentPalette(x + hue));
84 | }
85 | break;
86 |
87 | case 3:
88 | for (int y = 0; y < VPANEL_H; y++) {
89 | n = quadwave8(y * 2 - theta) / scale;
90 | effects.setPixel(n, y, effects.ColorFromCurrentPalette(y + hue));
91 | if (waveCount == 2)
92 | effects.setPixel(maxX - n, y, effects.ColorFromCurrentPalette(y + hue));
93 | }
94 | break;
95 | }
96 |
97 | effects.DimAll(220);
98 |
99 |
100 | if (thetaUpdate >= thetaUpdateFrequency) {
101 | thetaUpdate = 0;
102 | theta++;
103 | }
104 | else {
105 | thetaUpdate++;
106 | }
107 |
108 | if (hueUpdate >= hueUpdateFrequency) {
109 | hueUpdate = 0;
110 | hue++;
111 | }
112 | else {
113 | hueUpdate++;
114 | }
115 |
116 | effects.ShowFrame();
117 |
118 | return 0;
119 | }
120 | };
121 |
122 | #endif
123 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/Patterns.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Original Copyright (c) 2014 Jason Coon
4 | *
5 | * Modified by Codetastic 2024
6 | *
7 | */
8 |
9 | #ifndef Patterns_H
10 | #define Patterns_H
11 |
12 | #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
13 |
14 | #include "Vector2.hpp"
15 | #include "Boid.hpp"
16 | #include "Attractor.hpp"
17 |
18 | /*
19 | * Note from mrfaptastic:
20 | *
21 | * Commented out patterns are due to the fact they either didn't work properly with a non-square display,
22 | * or from my personal opinion, are crap.
23 | */
24 | #include "PatternStarfield.hpp" // new 2024
25 | #include "PatternAttract.hpp"
26 | #include "PatternBounce.hpp" // Doesn't seem to work, omitting.
27 | #include "PatternCube.hpp" // Doesn't seem to work, omitting.
28 | #include "PatternElectricMandala.hpp"
29 | #include "PatternFireKoz.hpp" // Doesn't seem to work, omitting.
30 | #include "PatternFlock.hpp"
31 | #include "PatternFlowField.hpp"
32 | #include "PatternIncrementalDrift.hpp"
33 | #include "PatternIncrementalDrift2.hpp" // Doesn't seem to work, omitting.
34 | #include "PatternInfinity.hpp"
35 | #include "PatternMaze.hpp" // ??
36 | #include "PatternMunch.hpp"
37 | //#include "PatternNoiseSmearing.hpp"
38 | #include "PatternPendulumWave.hpp"
39 | #include "PatternPlasma.hpp"
40 | #include "PatternRadar.hpp"
41 | #include "PatternSimplexNoise.hpp"
42 | #include "PatternSnake.hpp"
43 | #include "PatternSpiral.hpp"
44 | #include "PatternSpiro.hpp"
45 | #include "PatternWave.hpp"
46 | #include "PatternRain.hpp"
47 | #include "PatternJuliaSetFractal.hpp"
48 | #include "PatternRain.hpp"
49 | #include "PatternFireworks.hpp"
50 |
51 |
52 |
53 | class Patterns {
54 | private:
55 |
56 | PatternStarfield starfield;
57 | PatternAttract attract;
58 | PatternBounce bounce;
59 | PatternCube cube;
60 | PatternElectricMandala electricMandala;
61 | PatternFireKoz fire;
62 | PatternFlock flock;
63 | PatternFlowField flowField;
64 | PatternIncrementalDrift incrementalDrift;
65 | PatternIncrementalDrift2 incrementalDrift2;
66 | PatternInfinity infinity;
67 | PatternMaze maze;
68 | PatternMunch munch;
69 | PatternPendulumWave pendwave;
70 | PatternPlasma plasma;
71 | PatternRadar radar;
72 | PatternSimplexNoise simpnoise;
73 | PatternSnake snake;
74 | PatternSpiral spiral;
75 | PatternSpiro spiro;
76 | PatternWave wave;
77 | PatternJuliaSet juliaSet;
78 |
79 | PatternRain rain;
80 | PatternFirework fireworks;
81 |
82 |
83 | std::vector availablePatterns = {
84 | &juliaSet,
85 | &starfield,
86 | &attract,
87 | &bounce,
88 | &cube,
89 | &electricMandala,
90 | &fire,
91 | &flock,
92 | &spiro,
93 | &radar,
94 | &flowField,
95 | &incrementalDrift,
96 | &incrementalDrift2,
97 | &infinity,
98 | &maze,
99 | &munch,
100 | &pendwave,
101 | &plasma,
102 | &radar,
103 | &simpnoise,
104 | &spiro,
105 | &wave,
106 | &rain,
107 | &fireworks
108 | };
109 |
110 | int currentIndex = 0;
111 | Drawable* currentItem;
112 |
113 | int getCurrentIndex() {
114 | return currentIndex;
115 | }
116 |
117 |
118 | public:
119 | Patterns() {
120 | this->currentItem = availablePatterns[0];
121 | this->currentItem->start();
122 | }
123 |
124 | void stop() {
125 | if (currentItem)
126 | currentItem->stop();
127 | }
128 |
129 | void start() {
130 | if (currentItem)
131 | currentItem->start();
132 | }
133 |
134 | void moveTo(int index)
135 | {
136 | index = ((index >= availablePatterns.size()) || (index < 0)) ? 0 : index;
137 |
138 | if (currentItem)
139 | currentItem->stop();
140 |
141 | currentIndex = index;
142 | currentItem = availablePatterns[currentIndex];
143 |
144 | Serial.print("Changing pattern to: ");
145 | Serial.println(getCurrentPatternName());
146 |
147 | if (currentItem)
148 | currentItem->start();
149 |
150 | } // index
151 |
152 |
153 | void move(int step) {
154 |
155 | currentIndex += step;
156 |
157 | if (currentIndex >= availablePatterns.size()) currentIndex = 0;
158 | else if (currentIndex < 0) currentIndex = 0;
159 |
160 | moveTo(currentIndex);
161 | }
162 |
163 | void moveRandom(int step) {
164 | int rand_index = random(0, availablePatterns.size()-1);
165 | moveTo(rand_index);
166 | }
167 |
168 | unsigned int drawFrame() {
169 | return currentItem->drawFrame();
170 | }
171 |
172 | void listPatterns() {
173 | Serial.println(F("{"));
174 | Serial.print(F(" \"count\": "));
175 | Serial.print(availablePatterns.size());
176 | Serial.println(",");
177 | Serial.println(F(" \"results\": ["));
178 |
179 | for (size_t i = 0; i < availablePatterns.size(); i++) {
180 | Serial.print(F(" \""));
181 | Serial.print(i, DEC);
182 | Serial.print(F(": "));
183 | Serial.print(availablePatterns[i]->name);
184 | if (i == availablePatterns.size() - 1)
185 | Serial.println(F("\""));
186 | else
187 | Serial.println(F("\","));
188 | }
189 |
190 | Serial.println(" ]");
191 | Serial.println("}");
192 | }
193 |
194 | char * getCurrentPatternName()
195 | {
196 | return currentItem->name;
197 | }
198 | /*
199 | bool setPattern(String name) {
200 |
201 | for (size_t i = 0; i < availablePatterns.size(); i++) {
202 | if (name.compareTo(availablePatterns[i]->name) == 0) {
203 | moveTo(i);
204 | return true;
205 | }
206 | }
207 |
208 | return false;
209 | }
210 |
211 | */
212 | bool setPattern(int index) {
213 | if (index >= availablePatterns.size() || index < 0)
214 | return false;
215 |
216 | moveTo(index);
217 |
218 | return true;
219 | }
220 | };
221 |
222 | #endif
--------------------------------------------------------------------------------
/examples/AuroraDemo/README.md:
--------------------------------------------------------------------------------
1 | ## Aurora Demo
2 | * This demonstrates a combination of the following libraries:
3 | - "ESP32-HUB75-MatrixPanel-DMA" to send pixel data to the physical panels in combination with its in-built "VirtualMatrix" class to create a virtual display of chained panels, so the graphical effects of the Aurora demonstrations can be shown over a 'bigger' grid of physical panels acting as one big display.
4 | - "GFX_Lite" to provide a simple graphics library for drawing on the virtual display.
5 | - Note: GFX_Lite is a fork of AdaFruitGFX and FastLED library combined together, with a focus on simplicity and ease of use.
6 |
7 | ## Instructions
8 | * Use the serial input to advance through the patterns, or to toggle auto advance.
9 | * Sending 'n' will advance to the next pattern, 'p' will go to the previous pattern. Sending 'a' will toggle auto advance on and off.
10 |
--------------------------------------------------------------------------------
/examples/AuroraDemo/Vector2.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Aurora: https://github.com/pixelmatix/aurora
3 | * Copyright (c) 2014 Jason Coon
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | * this software and associated documentation files (the "Software"), to deal in
7 | * the Software without restriction, including without limitation the rights to
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | * the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef Vector_H
24 | #define Vector_H
25 |
26 | template
27 | class Vector2 {
28 | public:
29 | T x, y;
30 |
31 | Vector2() :x(0), y(0) {}
32 | Vector2(T x, T y) : x(x), y(y) {}
33 | Vector2(const Vector2& v) : x(v.x), y(v.y) {}
34 |
35 | Vector2& operator=(const Vector2& v) {
36 | x = v.x;
37 | y = v.y;
38 | return *this;
39 | }
40 |
41 | bool isEmpty() {
42 | return x == 0 && y == 0;
43 | }
44 |
45 | bool operator==(Vector2& v) {
46 | return x == v.x && y == v.y;
47 | }
48 |
49 | bool operator!=(Vector2& v) {
50 | return !(x == y);
51 | }
52 |
53 | Vector2 operator+(Vector2& v) {
54 | return Vector2(x + v.x, y + v.y);
55 | }
56 | Vector2 operator-(Vector2& v) {
57 | return Vector2(x - v.x, y - v.y);
58 | }
59 |
60 | Vector2& operator+=(Vector2& v) {
61 | x += v.x;
62 | y += v.y;
63 | return *this;
64 | }
65 | Vector2& operator-=(Vector2& v) {
66 | x -= v.x;
67 | y -= v.y;
68 | return *this;
69 | }
70 |
71 | Vector2 operator+(double s) {
72 | return Vector2(x + s, y + s);
73 | }
74 | Vector2 operator-(double s) {
75 | return Vector2(x - s, y - s);
76 | }
77 | Vector2 operator*(double s) {
78 | return Vector2(x * s, y * s);
79 | }
80 | Vector2 operator/(double s) {
81 | return Vector2(x / s, y / s);
82 | }
83 |
84 | Vector2& operator+=(double s) {
85 | x += s;
86 | y += s;
87 | return *this;
88 | }
89 | Vector2& operator-=(double s) {
90 | x -= s;
91 | y -= s;
92 | return *this;
93 | }
94 | Vector2& operator*=(double s) {
95 | x *= s;
96 | y *= s;
97 | return *this;
98 | }
99 | Vector2& operator/=(double s) {
100 | x /= s;
101 | y /= s;
102 | return *this;
103 | }
104 |
105 | void set(T x, T y) {
106 | this->x = x;
107 | this->y = y;
108 | }
109 |
110 | void rotate(double deg) {
111 | double theta = deg / 180.0 * M_PI;
112 | double c = cos(theta);
113 | double s = sin(theta);
114 | double tx = x * c - y * s;
115 | double ty = x * s + y * c;
116 | x = tx;
117 | y = ty;
118 | }
119 |
120 | Vector2& normalize() {
121 | if (length() == 0) return *this;
122 | *this *= (1.0 / length());
123 | return *this;
124 | }
125 |
126 | float dist(Vector2 v) const {
127 | Vector2 d(v.x - x, v.y - y);
128 | return d.length();
129 | }
130 | float length() const {
131 | return sqrt(x * x + y * y);
132 | }
133 |
134 | float mag() const {
135 | return length();
136 | }
137 |
138 | float magSq() {
139 | return (x * x + y * y);
140 | }
141 |
142 | void truncate(double length) {
143 | double angle = atan2f(y, x);
144 | x = length * cos(angle);
145 | y = length * sin(angle);
146 | }
147 |
148 | Vector2 ortho() const {
149 | return Vector2(y, -x);
150 | }
151 |
152 | static float dot(Vector2 v1, Vector2 v2) {
153 | return v1.x * v2.x + v1.y * v2.y;
154 | }
155 | static float cross(Vector2 v1, Vector2 v2) {
156 | return (v1.x * v2.y) - (v1.y * v2.x);
157 | }
158 |
159 | void limit(float max) {
160 | if (magSq() > max*max) {
161 | normalize();
162 | *this *= max;
163 | }
164 | }
165 | };
166 |
167 | typedef Vector2 PVector;
168 |
169 | #endif
170 |
--------------------------------------------------------------------------------
/examples/BitmapIcons/BitmapIcons.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "Dhole_weather_icons32px.h"
4 |
5 | /*--------------------- DEBUG -------------------------*/
6 | #define Sprintln(a) (Serial.println(a))
7 | #define SprintlnDEC(a, x) (Serial.println(a, x))
8 |
9 | #define Sprint(a) (Serial.print(a))
10 | #define SprintDEC(a, x) (Serial.print(a, x))
11 |
12 |
13 | /*--------------------- RGB DISPLAY PINS -------------------------*/
14 | #define R1_PIN 25
15 | #define G1_PIN 26
16 | #define B1_PIN 27
17 | #define R2_PIN 14
18 | #define G2_PIN 12
19 | #define B2_PIN 13
20 | #define A_PIN 23
21 | #define B_PIN 19 // Changed from library default
22 | #define C_PIN 5
23 | #define D_PIN 17
24 | #define E_PIN -1
25 | #define LAT_PIN 4
26 | #define OE_PIN 15
27 | #define CLK_PIN 16
28 |
29 |
30 | /*--------------------- MATRIX LILBRARY CONFIG -------------------------*/
31 | #define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
32 | #define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
33 | #define PANEL_CHAIN 1 // Total number of panels chained one to another
34 |
35 | MatrixPanel_I2S_DMA *dma_display = nullptr;
36 |
37 | // Module configuration
38 | HUB75_I2S_CFG mxconfig(
39 | PANEL_RES_X, // module width
40 | PANEL_RES_Y, // module height
41 | PANEL_CHAIN // Chain length
42 | );
43 |
44 | /*
45 | //Another way of creating config structure
46 | //Custom pin mapping for all pins
47 | HUB75_I2S_CFG::i2s_pins _pins={R1, G1, BL1, R2, G2, BL2, CH_A, CH_B, CH_C, CH_D, CH_E, LAT, OE, CLK};
48 | HUB75_I2S_CFG mxconfig(
49 | 64, // width
50 | 64, // height
51 | 4, // chain length
52 | _pins, // pin mapping
53 | HUB75_I2S_CFG::FM6126A // driver chip
54 | );
55 |
56 | */
57 |
58 |
59 | //mxconfig.gpio.e = -1; // Assign a pin if you have a 64x64 panel
60 | //mxconfig.clkphase = false; // Change this if you have issues with ghosting.
61 | //mxconfig.driver = HUB75_I2S_CFG::FM6126A; // Change this according to your pane.
62 |
63 |
64 | /*
65 | * Wifi Logo, generated with the following steps:
66 | *
67 | * Python and Paint.Net needs to be installed.
68 | *
69 | * 1. SAVE BITMAP AS 1BIT COLOUR in paint.net
70 | * 2. Run: bmp2hex.py -i -x
71 | * 3. Copy paste output into sketch.
72 | *
73 | */
74 |
75 | const char wifi_image1bit[] PROGMEM = {
76 | 0x00,0x00,0x00,0xf8,0x1f,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x01,0x00,
77 | 0x00,0x00,0x00,0xf0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0x1f,
78 | 0x00,0x00,0x00,0x00,0xfe,0x07,0xe0,0x7f,0x00,0x00,0x00,0x80,0xff,0x00,0x00,
79 | 0xff,0x01,0x00,0x00,0xc0,0x1f,0x00,0x00,0xf8,0x03,0x00,0x00,0xe0,0x0f,0x00,
80 | 0x00,0xf0,0x07,0x00,0x00,0xf0,0x03,0xf0,0x0f,0xc0,0x0f,0x00,0x00,0xe0,0x01,
81 | 0xff,0xff,0x80,0x07,0x00,0x00,0xc0,0xc0,0xff,0xff,0x03,0x03,0x00,0x00,0x00,
82 | 0xe0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0xf8,0x0f,0xf0,0x1f,0x00,0x00,0x00,
83 | 0x00,0xfc,0x01,0x80,0x3f,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x3e,0x00,0x00,
84 | 0x00,0x00,0x38,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x10,0xe0,0x07,0x08,0x00,
85 | 0x00,0x00,0x00,0x00,0xfc,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x7f,0x00,
86 | 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xf8,
87 | 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
88 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
89 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,
90 | 0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x07,0x00,0x00,0x00,0x00,
91 | 0x00,0x00,0xe0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,
92 | 0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
93 | 0x00 };
94 |
95 |
96 | void drawXbm565(int x, int y, int width, int height, const char *xbm, uint16_t color = 0xffff)
97 | {
98 | if (width % 8 != 0) {
99 | width = ((width / 8) + 1) * 8;
100 | }
101 | for (int i = 0; i < width * height / 8; i++ ) {
102 | unsigned char charColumn = pgm_read_byte(xbm + i);
103 | for (int j = 0; j < 8; j++) {
104 | int targetX = (i * 8 + j) % width + x;
105 | int targetY = (8 * i / (width)) + y;
106 | if (bitRead(charColumn, j)) {
107 | dma_display->drawPixel(targetX, targetY, color);
108 | }
109 | }
110 | }
111 | }
112 |
113 | /* Bitmaps */
114 | int current_icon = 0;
115 | static int num_icons = 22;
116 |
117 | static char icon_name[22][30] = {
118 | "cloud_moon_bits",
119 | "cloud_sun_bits",
120 | "clouds_bits",
121 | "cloud_wind_moon_bits",
122 | "cloud_wind_sun_bits",
123 | "cloud_wind_bits",
124 | "cloud_bits",
125 | "lightning_bits",
126 | "moon_bits",
127 | "rain0_sun_bits",
128 | "rain0_bits",
129 | "rain1_moon_bits",
130 | "rain1_sun_bits",
131 | "rain1_bits",
132 | "rain2_bits",
133 | "rain_lightning_bits",
134 | "rain_snow_bits",
135 | "snow_moon_bits",
136 | "snow_sun_bits",
137 | "snow_bits",
138 | "sun_bits",
139 | "wind_bits" };
140 |
141 | static char *icon_bits[22] = { cloud_moon_bits,
142 | cloud_sun_bits,
143 | clouds_bits,
144 | cloud_wind_moon_bits,
145 | cloud_wind_sun_bits,
146 | cloud_wind_bits,
147 | cloud_bits,
148 | lightning_bits,
149 | moon_bits,
150 | rain0_sun_bits,
151 | rain0_bits,
152 | rain1_moon_bits,
153 | rain1_sun_bits,
154 | rain1_bits,
155 | rain2_bits,
156 | rain_lightning_bits,
157 | rain_snow_bits,
158 | snow_moon_bits,
159 | snow_sun_bits,
160 | snow_bits,
161 | sun_bits,
162 | wind_bits};
163 |
164 |
165 |
166 | void setup() {
167 |
168 | // put your setup code here, to run once:
169 | delay(1000); Serial.begin(115200); delay(200);
170 |
171 |
172 | /************** DISPLAY **************/
173 | Sprintln("...Starting Display");
174 | dma_display = new MatrixPanel_I2S_DMA(mxconfig);
175 | dma_display->begin();
176 | dma_display->setBrightness8(90); //0-255
177 | dma_display->clearScreen();
178 |
179 | dma_display->fillScreen(dma_display->color444(0, 1, 0));
180 |
181 | // Fade a Red Wifi Logo In
182 | for (int r=0; r < 255; r++ )
183 | {
184 | drawXbm565(0,0,64,32, wifi_image1bit, dma_display->color565(r,0,0));
185 | delay(10);
186 | }
187 |
188 | delay(2000);
189 | dma_display->clearScreen();
190 | }
191 |
192 |
193 | void loop() {
194 |
195 | // Loop through Weather Icons
196 | Serial.print("Showing icon ");
197 | Serial.println(icon_name[current_icon]);
198 | drawXbm565(0,0, 32, 32, icon_bits[current_icon]);
199 |
200 | current_icon = (current_icon +1 ) % num_icons;
201 | delay(2000);
202 | dma_display->clearScreen();
203 |
204 | }
--------------------------------------------------------------------------------
/examples/BitmapIcons/README.md:
--------------------------------------------------------------------------------
1 | # Xbm Bitmap example
2 | ## Requirements
3 | * To generate the required Xbm data to be copied into the Sketch. Have python and [paint.net](https://www.getpaint.net/) installed.
4 | * Bitmap should match the resolution of your display configuration.
5 |
6 | ## Instructions
7 | 1. SAVE BITMAP AS 1BIT COLOUR in paint.net
8 | 1. Run: bmp2hex.py -i -x (e.g. "bmp2hex.py -i -x WiFi1bit.bmp")
9 | 1. Copy paste output into sketch.
10 |
11 | 
12 |
13 |
14 |
--------------------------------------------------------------------------------
/examples/BitmapIcons/WiFi1bit.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/BitmapIcons/WiFi1bit.bmp
--------------------------------------------------------------------------------
/examples/BitmapIcons/screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/examples/BitmapIcons/screenshot.jpg
--------------------------------------------------------------------------------
/examples/HueValueSpectrum/HueValueSpectrum.ino:
--------------------------------------------------------------------------------
1 | #define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
2 | #define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
3 | #define PANEL_CHAIN 1 // Total number of panels chained one to another
4 |
5 | #include
6 |
7 | MatrixPanel_I2S_DMA *dma_display = nullptr;
8 |
9 | void setup() {
10 |
11 | Serial.begin(112500);
12 |
13 |
14 | HUB75_I2S_CFG::i2s_pins _pins={
15 | 25, //R1_PIN,
16 | 26, //G1_PIN,
17 | 27, //B1_PIN,
18 | 14, //R2_PIN,
19 | 12, //G2_PIN,
20 | 13, //B2_PIN,
21 | 23, //A_PIN,
22 | 19, //B_PIN,
23 | 5, //C_PIN,
24 | 17, //D_PIN,
25 | 18, //E_PIN,
26 | 4, //LAT_PIN,
27 | 15, //OE_PIN,
28 | 16, //CLK_PIN
29 | };
30 | HUB75_I2S_CFG mxconfig(
31 | PANEL_RES_X, // Module width
32 | PANEL_RES_Y, // Module height
33 | PANEL_CHAIN // // chain length
34 | //,_pins // pin mapping -- uncomment if providing own custom pin mapping as per above.
35 | );
36 | //mxconfig.clkphase = false;
37 | //mxconfig.driver = HUB75_I2S_CFG::FM6126A;
38 |
39 | // Display Setup
40 | dma_display = new MatrixPanel_I2S_DMA(mxconfig);
41 | dma_display->begin();
42 | dma_display->clearScreen();
43 | }
44 |
45 | void loop() {
46 | // Canvas loop
47 | float t = (float) ((millis()%4000)/4000.f);
48 | float tt = (float) ((millis()%16000)/16000.f);
49 |
50 | for(int x = 0; x < (PANEL_RES_X*PANEL_CHAIN); x++)
51 | {
52 | // calculate the overal shade
53 | float f = (((sin(tt-(float)x/PANEL_RES_Y/32.)*2.f*PI)+1)/2)*255;
54 | // calculate hue spectrum into rgb
55 | float r = max(min(cosf(2.f*PI*(t+((float)x/PANEL_RES_Y+0.f)/3.f))+0.5f,1.f),0.f);
56 | float g = max(min(cosf(2.f*PI*(t+((float)x/PANEL_RES_Y+1.f)/3.f))+0.5f,1.f),0.f);
57 | float b = max(min(cosf(2.f*PI*(t+((float)x/PANEL_RES_Y+2.f)/3.f))+0.5f,1.f),0.f);
58 |
59 | // iterate pixels for every row
60 | for(int y = 0; y < PANEL_RES_Y; y++){
61 | if(y*2 < PANEL_RES_Y){
62 | // top-middle part of screen, transition of value
63 | float t = (2.f*y+1)/PANEL_RES_Y;
64 | dma_display->drawPixelRGB888(x,y,
65 | (r*t)*f,
66 | (g*t)*f,
67 | (b*t)*f
68 | );
69 | }else{
70 | // middle to bottom of screen, transition of saturation
71 | float t = (2.f*(PANEL_RES_Y-y)-1)/PANEL_RES_Y;
72 | dma_display->drawPixelRGB888(x,y,
73 | (r*t+1-t)*f,
74 | (g*t+1-t)*f,
75 | (b*t+1-t)*f
76 | );
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/examples/PIO_TestPatterns/README.md:
--------------------------------------------------------------------------------
1 | # Test Patterns
2 |
3 | Simple solid colors, gradients and test line patterns, could be used to test matrices for proper operation, flickering and estimate fillrate timings.
4 |
5 | It is also used in CI test builds to check different build flags scenarios.
6 |
7 | Should be build and uploaded as a [platformio](https://platformio.org/) project
8 |
9 |
10 | To build with Arduino's framework use
11 | ```
12 | pio run -t upload
13 | ```
14 |
15 | To build using ESP32 IDF with arduino's component use
16 | ```
17 | pio run -t upload -e idfarduino
18 | ```
19 |
--------------------------------------------------------------------------------
/examples/PIO_TestPatterns/platformio.ini:
--------------------------------------------------------------------------------
1 | [platformio]
2 | default_envs = esp32
3 | description = HUB75 ESP32 I2S DMA test patterns example
4 | ;src_dir = src
5 |
6 | [env]
7 | platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.13/platform-espressif32.zip
8 | board = wemos_d1_mini32
9 | lib_deps =
10 | fastled/FastLED
11 | Wire
12 | adafruit/Adafruit BusIO
13 | adafruit/Adafruit GFX Library
14 | https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA.git
15 | upload_speed = 460800
16 | monitor_speed = 115200
17 | monitor_filters = esp32_exception_decoder
18 |
19 | [env:esp32]
20 | framework = arduino
21 |
22 | [env:esp32idf]
23 | framework = arduino, espidf
24 |
--------------------------------------------------------------------------------
/examples/PIO_TestPatterns/sdkconfig.defaults:
--------------------------------------------------------------------------------
1 | # Override some defaults to enable Arduino framework
2 | CONFIG_ENABLE_ARDUINO_DEPENDS=y
3 | CONFIG_AUTOSTART_ARDUINO=y
4 | CONFIG_ARDUINO_RUN_CORE1=y
5 | CONFIG_ARDUINO_RUNNING_CORE=1
6 | CONFIG_ARDUINO_EVENT_RUN_CORE1=y
7 | CONFIG_ARDUINO_EVENT_RUNNING_CORE=1
8 | CONFIG_ARDUINO_UDP_RUN_CORE1=y
9 | CONFIG_ARDUINO_UDP_RUNNING_CORE=1
10 | CONFIG_DISABLE_HAL_LOCKS=y
11 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y
12 | CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1
13 | CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y
14 | CONFIG_ARDUHAL_PARTITION_SCHEME="default"
15 | CONFIG_AUTOCONNECT_WIFI=y
16 | CONFIG_ARDUINO_SELECTIVE_WiFi=y
17 | CONFIG_MBEDTLS_PSK_MODES=y
18 | CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
19 | CONFIG_FREERTOS_HZ=1000
--------------------------------------------------------------------------------
/examples/PIO_TestPatterns/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This file was automatically generated for projects
2 | # without default 'CMakeLists.txt' file.
3 |
4 | FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
5 |
6 | idf_component_register(SRCS ${app_sources})
7 |
--------------------------------------------------------------------------------
/examples/PIO_TestPatterns/src/main.h:
--------------------------------------------------------------------------------
1 |
2 | #include
3 |
4 | #define BAUD_RATE 115200 // serial debug port baud rate
5 |
6 | void buffclear(CRGB *buf);
7 | uint16_t XY16( uint16_t x, uint16_t y);
8 | void mxfill(CRGB *leds);
9 | uint16_t colorWheel(uint8_t pos);
10 | void drawText(int colorWheelOffset);
--------------------------------------------------------------------------------
/examples/Pixel_Mapping_Test/Pixel_Mapping_Test.ino:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | Description:
3 |
4 | The underlying implementation of the ESP32-HUB75-MatrixPanel-I2S-DMA only
5 | supports output to HALF scan panels - which means outputting
6 | two lines at the same time, 16 or 32 rows apart if a 32px or 64px high panel
7 | respectively.
8 | This cannot be changed at the DMA layer as it would require a messy and complex
9 | rebuild of the library's internals.
10 |
11 | However, it is possible to connect QUARTER (i.e. FOUR lines updated in parallel)
12 | scan panels to this same library and
13 | 'trick' the output to work correctly on these panels by way of adjusting the
14 | pixel co-ordinates that are 'sent' to the ESP32-HUB75-MatrixPanel-I2S-DMA
15 | library.
16 |
17 | **************************************************************************/
18 |
19 | /* Use the Virtual Display class to re-map co-ordinates such that they draw
20 | correctly on a 32x16 1/4 or 64x32 1/8 Scan panel (or chain of such panels).
21 | */
22 | #include "ESP32-VirtualMatrixPanel-I2S-DMA.h"
23 |
24 | // Define custom class derived from VirtualMatrixPanel
25 | class CustomPxBasePanel : public VirtualMatrixPanel
26 | {
27 | public:
28 | using VirtualMatrixPanel::VirtualMatrixPanel; // inherit VirtualMatrixPanel's constructor(s)
29 |
30 | protected:
31 |
32 | VirtualCoords getCoords(int16_t x, int16_t y); // custom getCoords() method for specific pixel mapping
33 |
34 | };
35 |
36 | // custom getCoords() method for specific pixel mapping
37 | inline VirtualCoords CustomPxBasePanel ::getCoords(int16_t x, int16_t y) {
38 |
39 | coords = VirtualMatrixPanel::getCoords(x, y); // call base class method to update coords for chaining approach
40 |
41 | if ( coords.x == -1 || coords.y == -1 ) { // Co-ordinates go from 0 to X-1 remember! width() and height() are out of range!
42 | return coords;
43 | }
44 |
45 | uint8_t pxbase = panelResX; // pixel base
46 | // mapper for panels with 32 pixs height (64x32 or 32x32)
47 | if (panelResY == 32)
48 | {
49 | if ((coords.y & 8) == 0)
50 | {
51 | coords.x += ((coords.x / pxbase) + 1) * pxbase; // 1st, 3rd 'block' of 8 rows of pixels
52 | }
53 | else
54 | {
55 | coords.x += (coords.x / pxbase) * pxbase; // 2nd, 4th 'block' of 8 rows of pixels
56 | }
57 | coords.y = (coords.y >> 4) * 8 + (coords.y & 0b00000111);
58 | }
59 |
60 | // mapper for panels with 16 pixs height (32x16 1/4)
61 | else if (panelResY == 16)
62 | {
63 | if ((coords.y & 4) == 0)
64 | {
65 | // 1. Normal line, from left to right
66 | coords.x += ((coords.x / pxbase) + 1) * pxbase; // 1st, 3rd 'block' of 4 rows of pixels
67 | //2. in case the line filled from right to left, use this (and comment 1st)
68 | //coords.x = ((coords.x / pxbase) + 1) * 2 * pxbase - (coords.x % pxbase) - 1;
69 | }
70 | else
71 | {
72 | coords.x += (coords.x / pxbase) * pxbase; // 2nd, 4th 'block' of 4 rows of pixels
73 | }
74 | coords.y = (coords.y >> 3) * 4 + (coords.y & 0b00000011);
75 | }
76 | return coords;
77 | }
78 |
79 | // Panel configuration
80 | #define PANEL_RES_X 32 // Number of pixels wide of each INDIVIDUAL panel module.
81 | #define PANEL_RES_Y 16 // Number of pixels tall of each INDIVIDUAL panel module.
82 |
83 | // Use a single panel for tests
84 | #define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
85 | #define NUM_COLS 1 // Number of INDIVIDUAL PANELS per ROW
86 |
87 | // Chain settings, do not cnahge
88 | #define SERPENT true
89 | #define TOPDOWN false
90 | #define VIRTUAL_MATRIX_CHAIN_TYPE CHAIN_BOTTOM_RIGHT_UP
91 |
92 | // placeholder for the matrix object
93 | MatrixPanel_I2S_DMA *dma_display = nullptr;
94 |
95 | // placeholder for the virtual display object
96 | CustomPxBasePanel *FourScanPanel = nullptr;
97 |
98 | /******************************************************************************
99 | Setup!
100 | ******************************************************************************/
101 | void setup()
102 | {
103 | HUB75_I2S_CFG mxconfig(
104 | PANEL_RES_X * 2, // DO NOT CHANGE THIS
105 | PANEL_RES_Y / 2, // DO NOT CHANGE THIS
106 | NUM_ROWS * NUM_COLS // DO NOT CHANGE THIS
107 | //,_pins // Uncomment to enable custom pins
108 | );
109 |
110 | mxconfig.clkphase = false; // Change this if you see pixels showing up shifted wrongly by one column the left or right.
111 |
112 | // OK, now we can create our matrix object
113 | dma_display = new MatrixPanel_I2S_DMA(mxconfig);
114 |
115 | // let's adjust default brightness to about 75%
116 | dma_display->setBrightness8(40); // range is 0-255, 0 - 0%, 255 - 100%
117 |
118 | // Allocate memory and start DMA display
119 | if ( not dma_display->begin() )
120 | Serial.println("****** !KABOOM! I2S memory allocation failed ***********");
121 |
122 |
123 | dma_display->clearScreen();
124 | delay(500);
125 |
126 | // create FourScanPanellay object based on our newly created dma_display object
127 | FourScanPanel = new CustomPxBasePanel ((*dma_display), NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y, VIRTUAL_MATRIX_CHAIN_TYPE);
128 |
129 | }
130 |
131 |
132 | void loop() {
133 | for (int i = 0; i < FourScanPanel->height(); i++)
134 | {
135 | for (int j = 0; j < FourScanPanel->width(); j++)
136 | {
137 | FourScanPanel->drawPixel(j, i, FourScanPanel->color565(255, 0, 0));
138 | delay(30);
139 | }
140 | }
141 | delay(2000);
142 | dma_display->clearScreen();
143 | } // end loop
--------------------------------------------------------------------------------
/examples/Pixel_Mapping_Test/README.md:
--------------------------------------------------------------------------------
1 | ## Four Scan Panel pixel mapping test and tune
2 | This example is to help you set up pixel coordinate mapping on most common cases of Four_Scan_Panels such as 64x32 1/8 or 32x16 1/4. Please follow the steps below in sequence.
3 |
4 | ### 1. Run this code on a single panel
5 | If the panel lines are filled sequentially, from left to right and from top to bottom, then you don't need to change the setting.
6 |
7 | ### 2. If your panel filling in parts
8 | Most often, the panel rows are filled in small segments, 4, 8 or 16 pixels (there are other values). This number is the pixel base of the panel. Substitute it into line 45 of the example and run the code again.
9 |
10 | ### 3. Wrong order of rows
11 | At this point, your panel should already be filled with whole rows. If the top row is not the first to be filled, swap the expressions, marked in the comments as "1st, 3rd 'block' of rows" with "2nd, 4th 'block' of rows" one.
12 |
13 | ### 4. Wrong filling direction
14 | If any block of rows is filled from right to left, change the formula according to the example shown in the lines 65-68 of the code.
15 |
16 | ### Conclusion
17 | If your panel works correctly now - congratulations. But if not - it's okay. There are many types of different panels and it is impossible to foresee all the nuances. Create an issue and you will be helped!
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | | Example Name |Description |
2 | |--|--|
3 | |1_SimpleTestShapes |Example for new starters - how to display basic shapes. |
4 | |2_PatternPlasma |Example for new starters - how to display a cool plasma pattern. |
5 | |3_FM6126Panel |Example for new starters - how to initialise FM6126/FM6126A panels with this library.
6 | |AnimatedGIFPanel |Using Larry Bank's GIF Decoder to display animated GIFs. |
7 | |AuroraDemo |Simple example demonstrating various animated effects. |
8 | |BitmapIcons |Simple example of how to display a bitmap image to the display. |
9 | |ChainedPanels |Popular example on how to use the 'VirtualMatrixPanel' class to chain multiple LED Matrix Panels to form a much bigger display! Refer to the README within this example's folder! |
10 | |ChainedPanelsAuroraDemo |As above, but showing a large trippy plasma animation. |
11 | |ChainedPanelsScreenBuffer |Using the same 'VirtualMatrixPanel' class but also implementing a FastLED off-screen pixel buffer to do cool stuff. |
12 | |One_Quarter_1_4_ScanPanel |Using this library with a 32w x 16h 1/4 Scan LED Matrix Panel. Custom co-ordinate remapping logic required. NOT WORKING. |
13 | |One_Eighth_1_8_ScanPanel |Using this library with a 64w x 32h 1/8 Scan LED Matrix Panel. Custom co-ordinate remapping logic required.
14 | |PIO_TestPatterns |Non-Arduino example of how to display basic shapes. |
15 |
--------------------------------------------------------------------------------
/examples/VirtualMatrixPanel/README.md:
--------------------------------------------------------------------------------
1 | # The 'VirtualMatrixPanel_T' class
2 | The `VirtualMatrixPanel_T` is used to perform pixel re-mapping in order to support the following use-cases that can be used together:
3 | 1. To create a larger display based on a chain of individual physical panels connected electrically in a Serpentine or Zig-Zag manner.
4 | 2. To provide support for physical panels with non-standard (i.e. Not a 1/2 scan panel) pixel mapping approaches. This is often seen with 1/4 scan outdoor panels.
5 |
6 | ## 1. Chaining individual LED matrix panels to make a larger virtual display ##
7 |
8 | This is the PatternPlasma Demo adopted for use with multiple LED Matrix Panel displays arranged in a non standard order (i.e. a grid) to make a bigger display.
9 |
10 | 
11 |
12 | ### What do we mean by 'non standard order'? ###
13 |
14 | When you link / chain multiple panels together, the ESP32-HUB75-MatrixPanel-I2S-DMA library treats as one wide horizontal panel. This would be a 'standard' (default) order.
15 |
16 | Non-standard order is essentially the creation of a non-horizontal-only display that you can draw to in the same way you would any other display, with VirtualDisplay library looking after the pixel mapping to the physical chained panels.
17 |
18 | For example: You bought four (4) 64x32px panels, and wanted to use them to create a 128x64pixel display. You would use the VirtualMatrixPanel class.
19 |
20 | [Refer to this document](https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA/blob/master/doc/VirtualMatrixPanel.pdf) for an explanation and refer to this example on how to use.
21 |
22 |
23 | ### Steps to Use ###
24 |
25 | 1. [Refer to this document](https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA/blob/master/doc/VirtualMatrixPanel.pdf) for an explanation and refer to this example on how to use.
26 |
27 | 2. Read the `VirtualMatrixPanel.ino` code
28 |
29 | ## 2. Using this library with 1/4 Scan Panels (Four Scan)
30 |
31 | This library does not natively support 'Four Scan' 64x32 1/8 or 32x16 1/4 scan panels such [as this](https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/154) by default.
32 |
33 | ### Solution
34 | Read the `VirtualMatrixPanel.ino` code.
35 |
36 | The VirtualMatrixPanel_T class provides a way to additionally remap pixel for each individual panel by way of the `ScanTypeMapping` class.
37 |
38 | You can create your own custom per-panel pixel mapping class as well should you wish.
39 |
40 | ```cpp
41 | // --- Example 3: Single non-standard 1/4 Scan (Four-Scan 1/8) ---
42 |
43 | // Use an existing library user-contributed Scan Type pixel mapping
44 | using MyScanTypeMapping = ScanTypeMapping;
45 |
46 | // Create a pointer to the specific instantiation of the VirtualMatrixPanel_T class
47 | VirtualMatrixPanel_T* virtualDisp = nullptr;
48 | ```
49 |
50 | The library has these user-contributed additions, but given the variety of panels on the market, your success with any of these may vary.
51 |
52 | ```cpp
53 | FOUR_SCAN_32PX_HIGH, ///< Four-scan mode, 32-pixel high panels.
54 | FOUR_SCAN_16PX_HIGH, ///< Four-scan mode, 16-pixel high panels.
55 | FOUR_SCAN_64PX_HIGH, ///< Four-scan mode, 64-pixel high panels.
56 | FOUR_SCAN_40PX_HIGH ///< Four-scan mode, 40-pixel high panels.
57 | ```
--------------------------------------------------------------------------------
/examples/esp-idf/.gitignore:
--------------------------------------------------------------------------------
1 | # ESP-IDF default build directory
2 | build
3 |
4 | # Temporary files
5 | *.swp
6 |
7 | # lock files for examples and components
8 | dependencies.lock
9 |
10 | sdkconfig*
11 | # Unignore sdkconfig.defaults
12 | !sdkconfig.defaults
13 |
--------------------------------------------------------------------------------
/examples/esp-idf/with-gfx/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This is a boilerplate top-level project CMakeLists.txt file.
2 | # This is the primary file which CMake uses to learn how to build the project.
3 | #
4 | # Most of the important stuff happens in the 'main' directory.
5 | #
6 | # See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#example-project for more details.
7 | cmake_minimum_required(VERSION 3.5)
8 |
9 | include($ENV{IDF_PATH}/tools/cmake/project.cmake)
10 | project(with-gfx)
11 |
--------------------------------------------------------------------------------
/examples/esp-idf/with-gfx/README.md:
--------------------------------------------------------------------------------
1 | # ESP-IDF Example With Adafruit GFX Library
2 |
3 | This folder contains example code for using this library with `esp-idf` and the [Adafruit GFX library](https://github.com/adafruit/Adafruit-GFX-Library).
4 |
5 | First, follow the [Getting Started Guide for ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) to install ESP-IDF onto your computer.
6 |
7 | When you are ready to start your first project with this library, follow folow these steps:
8 |
9 | 1. Copy the files in this folder (and sub folders) into a new directory for your project.
10 | 1. Clone the required repositories:
11 | ```
12 | git clone https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA.git components/ESP32-HUB75-MatrixPanel-I2S-DMA
13 | git clone https://github.com/adafruit/Adafruit-GFX-Library.git components/Adafruit-GFX-Library
14 | git clone https://github.com/adafruit/Adafruit_BusIO.git components/Adafruit_BusIO
15 | git clone https://github.com/espressif/arduino-esp32.git components/arduino
16 | ```
17 | 1. Build your project: `idf.py build`
18 |
--------------------------------------------------------------------------------
/examples/esp-idf/with-gfx/components/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
5 |
--------------------------------------------------------------------------------
/examples/esp-idf/with-gfx/main/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(
2 | SRC_DIRS "." ${SRCDIRS}
3 | INCLUDE_DIRS ${INCLUDEDIRS}
4 | REQUIRES ESP32-HUB75-MatrixPanel-I2S-DMA
5 | )
6 |
--------------------------------------------------------------------------------
/examples/esp-idf/with-gfx/main/main.cpp:
--------------------------------------------------------------------------------
1 | #include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"
2 |
3 | MatrixPanel_I2S_DMA *dma_display = nullptr;
4 |
5 | extern "C" void app_main() {
6 | HUB75_I2S_CFG mxconfig(/* width = */ 64, /* height = */ 64, /* chain = */ 1);
7 |
8 | dma_display = new MatrixPanel_I2S_DMA(mxconfig);
9 | dma_display->begin();
10 | dma_display->setBrightness8(80);
11 | dma_display->clearScreen();
12 | // `println` is only available when the Adafruit GFX library is used.
13 | dma_display->println("Test message");
14 | }
15 |
--------------------------------------------------------------------------------
/examples/esp-idf/with-gfx/sdkconfig.defaults:
--------------------------------------------------------------------------------
1 | CONFIG_FREERTOS_HZ=1000
2 |
--------------------------------------------------------------------------------
/examples/esp-idf/without-gfx/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This is a boilerplate top-level project CMakeLists.txt file.
2 | # This is the primary file which CMake uses to learn how to build the project.
3 | #
4 | # Most of the important stuff happens in the 'main' directory.
5 | #
6 | # See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#example-project for more details.
7 | cmake_minimum_required(VERSION 3.5)
8 |
9 | include($ENV{IDF_PATH}/tools/cmake/project.cmake)
10 | project(without-gfx)
11 |
--------------------------------------------------------------------------------
/examples/esp-idf/without-gfx/README.md:
--------------------------------------------------------------------------------
1 | # ESP-IDF Example Without Adafruit GFX Library
2 |
3 | This folder contains example code for using this library with `esp-idf`.
4 |
5 | First, follow the [Getting Started Guide for ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) to install ESP-IDF onto your computer.
6 |
7 | When you are ready to start your first project with this library, follow folow these steps:
8 |
9 | 1. Copy the files in this folder (and sub folders) into a new directory for your project.
10 | 1. Clone the required repositories:
11 | ```
12 | git clone https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA.git components/ESP32-HUB75-MatrixPanel-I2S-DMA
13 | ```
14 | 1. Build your project: `idf.py build`
15 |
--------------------------------------------------------------------------------
/examples/esp-idf/without-gfx/components/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
5 |
--------------------------------------------------------------------------------
/examples/esp-idf/without-gfx/main/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | idf_component_register(
2 | SRC_DIRS "." ${SRCDIRS}
3 | INCLUDE_DIRS ${INCLUDEDIRS}
4 | REQUIRES ESP32-HUB75-MatrixPanel-I2S-DMA
5 | )
6 |
--------------------------------------------------------------------------------
/examples/esp-idf/without-gfx/main/main.cpp:
--------------------------------------------------------------------------------
1 | #include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"
2 |
3 | MatrixPanel_I2S_DMA *dma_display = nullptr;
4 |
5 | extern "C" void app_main() {
6 | HUB75_I2S_CFG mxconfig(/* width = */ 64, /* height = */ 64, /* chain = */ 1);
7 |
8 | dma_display = new MatrixPanel_I2S_DMA(mxconfig);
9 | dma_display->begin();
10 | dma_display->setBrightness8(80);
11 | dma_display->clearScreen();
12 | }
13 |
--------------------------------------------------------------------------------
/examples/esp-idf/without-gfx/sdkconfig.defaults:
--------------------------------------------------------------------------------
1 | CONFIG_ESP32_HUB75_USE_GFX=n
2 |
--------------------------------------------------------------------------------
/image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/image.jpg
--------------------------------------------------------------------------------
/keywords.txt:
--------------------------------------------------------------------------------
1 | RGB64x32MatrixPanel_I2S_DMA KEYWORD1
2 | MatrixPanel_I2S_DMA KEYWORD1
3 | Layer KEYWORD1
4 | fillScreen KEYWORD2
5 | clearScreen KEYWORD2
6 | fillScreenRGB888 KEYWORD2
7 | drawPixelRGB565 KEYWORD2
8 | drawPixelRGB888 KEYWORD2
9 | drawPixelRGB24 KEYWORD2
10 | drawIcon KEYWORD2
11 | color444 KEYWORD2
12 | color565 KEYWORD2
13 | color333 KEYWORD2
14 | flipDMABuffer KEYWORD2
15 | showDMABuffer KEYWORD2
16 | setPanelBrightness KEYWORD2
17 | setMinRefreshRate KEYWORD2
18 | RGB24 KEYWORD1
--------------------------------------------------------------------------------
/library.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ESP32 HUB75 LED MATRIX PANEL DMA Display",
3 | "version": "3.0.12",
4 | "description": "An Adafruit GFX compatible library for LED matrix modules which uses DMA for ultra-fast refresh rates and therefore very low CPU usage.",
5 | "keywords": "hub75, esp32, esp32s2, esp32s3, display, dma, rgb matrix",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git"
9 | },
10 | "authors": {
11 | "name": "MrCodetastic",
12 | "url": "https://github.com/mrcodetastic/"
13 | },
14 | "frameworks": [
15 | "arduino",
16 | "espidf"
17 | ],
18 | "platforms": [
19 | "espressif32"
20 | ],
21 | "headers": [
22 | "ESP32-HUB75-MatrixPanel-I2S-DMA.h", "ESP32-VirtualMatrixPanel-I2S-DMA.h"
23 | ],
24 | "examples": [
25 | {
26 | "name": "SimpleTestShapes",
27 | "base": "examples/1_SimpleTestShapes",
28 | "files": [
29 | "1_SimpleTestShapes.ino"
30 | ]
31 | },
32 | {
33 | "name": "Plasma Pattern",
34 | "base": "examples/2_PatternPlasma",
35 | "files": [
36 | "2_PatternPlasma.ino",
37 | "README.md"
38 | ]
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=ESP32 HUB75 LED MATRIX PANEL DMA Display
2 | version= 3.0.12
3 | author=MrCodetastic
4 | maintainer=MrCodetastic
5 | sentence=HUB75 LED Matrix Library for ESP32, ESP32-S2 and ESP32-S3
6 | paragraph=An Adafruit GFX compatible library for LED matrix modules which uses DMA for ultra-fast refresh rates and therefore very low CPU usage.
7 | category=Display
8 | url=https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA
9 | architectures=esp32,esp32s2,esp32s3
10 |
--------------------------------------------------------------------------------
/src/platforms/esp32/RGB_HUB75_PINS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/src/platforms/esp32/RGB_HUB75_PINS.png
--------------------------------------------------------------------------------
/src/platforms/esp32/esp32-default-pins.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define R1_PIN_DEFAULT 25
4 | #define G1_PIN_DEFAULT 26
5 | #define B1_PIN_DEFAULT 27
6 | #define R2_PIN_DEFAULT 14
7 | #define G2_PIN_DEFAULT 12
8 | #define B2_PIN_DEFAULT 13
9 |
10 | #define A_PIN_DEFAULT 23
11 | #define B_PIN_DEFAULT 19
12 | #define C_PIN_DEFAULT 5
13 | #define D_PIN_DEFAULT 17
14 | #define E_PIN_DEFAULT -1 // IMPORTANT: Change to a valid pin if using a 64x64px panel.
15 |
16 | #define LAT_PIN_DEFAULT 4
17 | #define OE_PIN_DEFAULT 15
18 | #define CLK_PIN_DEFAULT 16
19 |
--------------------------------------------------------------------------------
/src/platforms/esp32/esp32_i2s_parallel_dma.hpp:
--------------------------------------------------------------------------------
1 | /*----------------------------------------------------------------------------/
2 | Lovyan GFX - Graphics library for embedded devices.
3 |
4 | Original Source:
5 | https://github.com/lovyan03/LovyanGFX/
6 |
7 | Licence:
8 | [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt)
9 |
10 | Author:
11 | [lovyan03](https://twitter.com/lovyan03)
12 |
13 | Contributors:
14 | [ciniml](https://github.com/ciniml)
15 | [mongonta0716](https://github.com/mongonta0716)
16 | [tobozo](https://github.com/tobozo)
17 |
18 | Modified heavily for the ESP32 HUB75 DMA library by:
19 | [mrfaptastic](https://github.com/mrfaptastic)
20 |
21 | ------------------------------------------------------------------------------
22 |
23 | Putin’s Russia and its genocide of Ukrainians is a disgrace to humanity.
24 |
25 | https://www.reddit.com/r/ukraine/comments/xfuc6v/more_than_460_graves_have_already_been_found_in/
26 |
27 | /----------------------------------------------------------------------------*/
28 |
29 | #pragma once
30 |
31 | #include // memcpy
32 | #include
33 | #include
34 |
35 | #include
36 | #include
37 | //#include
38 | #include
39 | #include
40 | #if (ESP_IDF_VERSION_MAJOR == 5)
41 | #include //includes struct and reg
42 | #else
43 | #include
44 | #include
45 | #endif
46 |
47 | #include //includes struct and reg
48 |
49 |
50 | #define DMA_MAX (4096-4)
51 |
52 | // The type used for this SoC
53 | #define HUB75_DMA_DESCRIPTOR_T lldesc_t
54 |
55 |
56 | #if defined (CONFIG_IDF_TARGET_ESP32S2)
57 | #define ESP32_I2S_DEVICE I2S_NUM_0
58 | #else
59 | #define ESP32_I2S_DEVICE I2S_NUM_1
60 | #endif
61 |
62 | //----------------------------------------------------------------------------
63 |
64 | void IRAM_ATTR irq_hndlr(void* arg);
65 | i2s_dev_t* getDev();
66 |
67 | //----------------------------------------------------------------------------
68 |
69 | class Bus_Parallel16
70 | {
71 | public:
72 | Bus_Parallel16()
73 | {
74 |
75 | }
76 |
77 | struct config_t
78 | {
79 | // max 20MHz (when in 16 bit / 2 byte mode)
80 | uint32_t bus_freq = 10000000;
81 | int8_t pin_wr = -1; //
82 | int8_t pin_rd = -1;
83 | int8_t pin_rs = -1; // D/C
84 | bool invert_pclk = false;
85 | int8_t parallel_width = 16; // do not change
86 | union
87 | {
88 | int8_t pin_data[16];
89 | struct
90 | {
91 | int8_t pin_d0;
92 | int8_t pin_d1;
93 | int8_t pin_d2;
94 | int8_t pin_d3;
95 | int8_t pin_d4;
96 | int8_t pin_d5;
97 | int8_t pin_d6;
98 | int8_t pin_d7;
99 | int8_t pin_d8;
100 | int8_t pin_d9;
101 | int8_t pin_d10;
102 | int8_t pin_d11;
103 | int8_t pin_d12;
104 | int8_t pin_d13;
105 | int8_t pin_d14;
106 | int8_t pin_d15;
107 | };
108 | };
109 | };
110 |
111 | const config_t& config(void) const { return _cfg; }
112 | void config(const config_t& config);
113 |
114 | bool init(void) ;
115 | void release(void) ;
116 |
117 | void enable_double_dma_desc();
118 | bool allocate_dma_desc_memory(size_t len);
119 |
120 | void create_dma_desc_link(void *memory, size_t size, bool dmadesc_b = false);
121 |
122 | void dma_transfer_start();
123 | void dma_transfer_stop();
124 |
125 | void flip_dma_output_buffer(int buffer_id);
126 |
127 | private:
128 |
129 | void _init_pins() { };
130 |
131 | config_t _cfg;
132 |
133 | bool _double_dma_buffer = false;
134 | //bool _dmadesc_a_active = true;
135 |
136 | uint32_t _dmadesc_count = 0; // number of dma decriptors
137 | uint32_t _dmadesc_last = 0;
138 |
139 | uint32_t _dmadesc_a_idx = 0;
140 | uint32_t _dmadesc_b_idx = 0;
141 |
142 | HUB75_DMA_DESCRIPTOR_T* _dmadesc_a = nullptr;
143 | HUB75_DMA_DESCRIPTOR_T* _dmadesc_b = nullptr;
144 |
145 | /*
146 | HUB75_DMA_DESCRIPTOR_T* _dmadesc_blank = nullptr;
147 | uint16_t _blank_data[1024] = {0};
148 | */
149 |
150 | volatile i2s_dev_t* _dev;
151 |
152 |
153 |
154 | };
155 |
--------------------------------------------------------------------------------
/src/platforms/esp32c6/dma_parallel_io.hpp.notused:
--------------------------------------------------------------------------------
1 | /*
2 | Simple example of using the ESP32-C6's parallel IO peripheral for general-purpose
3 | parallel data output with DMA.
4 |
5 | Credits to ESPRESSIF them selfe, they made the first example:
6 |
7 | https://github.com/espressif/esp-idf/tree/release/v5.1/examples/peripherals/parlio/simple_rgb_led_matrix
8 |
9 | And Credits to the guy who implemented the S3 version of this library.
10 | There is a lot of resusable code
11 |
12 |
13 | */
14 |
15 |
16 | #pragma once
17 |
18 | #include
19 |
20 | #ifdef CONFIG_IDF_TARGET_ESP32C6
21 |
22 | #include "driver/parlio_tx.h"
23 |
24 | #include
25 | #include
26 | #include
27 |
28 |
29 | #define DMA_MAX (4096-4)
30 | #define HUB75_DMA_DESCRIPTOR_T dma_descriptor_t
31 |
32 |
33 | class Bus_Parallel16
34 | {
35 | public:
36 | Bus_Parallel16()
37 | {
38 |
39 | }
40 |
41 | struct config_t
42 | {
43 | // LCD_CAM peripheral number. No need to change (only 0 for ESP32-S3.)
44 | //int port = 0;
45 |
46 | // max 40MHz (when in 16 bit / 2 byte mode)
47 | uint32_t bus_freq = 10000000;
48 | int8_t pin_wr = -1;
49 | //int8_t pin_rd = -1;
50 | //int8_t pin_rs = -1; // D/C
51 | bool invert_pclk = false;
52 | union
53 | {
54 | int8_t pin_data[16];
55 | struct
56 | {
57 | int8_t pin_d0;
58 | int8_t pin_d1;
59 | int8_t pin_d2;
60 | int8_t pin_d3;
61 | int8_t pin_d4;
62 | int8_t pin_d5;
63 | int8_t pin_d6;
64 | int8_t pin_d7;
65 | int8_t pin_d8;
66 | int8_t pin_d9;
67 | int8_t pin_d10;
68 | int8_t pin_d11;
69 | int8_t pin_d12;
70 | int8_t pin_d13;
71 | int8_t pin_d14;
72 | int8_t pin_d15;
73 | };
74 | };
75 | };
76 |
77 | const config_t& config(void) const { return _cfg; }
78 | void config(const config_t& config);
79 |
80 | bool init(void) ;
81 |
82 | void release(void) ;
83 |
84 | void enable_double_dma_desc();
85 | bool allocate_dma_desc_memory(size_t len);
86 |
87 | void create_dma_desc_link(void *memory, size_t size, bool dmadesc_b = false);
88 |
89 | void dma_transfer_start();
90 | void dma_transfer_stop();
91 |
92 | void flip_dma_output_buffer(int back_buffer_id);
93 |
94 | private:
95 |
96 | config_t _cfg;
97 |
98 | gdma_channel_handle_t dma_chan;
99 |
100 | uint32_t _dmadesc_count = 0; // number of dma decriptors
101 |
102 | uint32_t _dmadesc_a_idx = 0;
103 | uint32_t _dmadesc_b_idx = 0;
104 |
105 | HUB75_DMA_DESCRIPTOR_T* _dmadesc_a = nullptr;
106 | HUB75_DMA_DESCRIPTOR_T* _dmadesc_b = nullptr;
107 |
108 | bool _double_dma_buffer = false;
109 | //bool _dmadesc_a_active = true;
110 |
111 | };
112 |
113 |
114 |
115 | #endif
--------------------------------------------------------------------------------
/src/platforms/esp32c6/esp32c6-default-pins.hpp.notused:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Avoid and QSPI pins
4 |
5 | #define R1_PIN_DEFAULT 7
6 | #define G1_PIN_DEFAULT 4
7 | #define B1_PIN_DEFAULT 1
8 | #define R2_PIN_DEFAULT 6
9 | #define G2_PIN_DEFAULT 3
10 | #define B2_PIN_DEFAULT 0
11 | #define A_PIN_DEFAULT 20
12 | #define B_PIN_DEFAULT 21
13 | #define C_PIN_DEFAULT 22
14 | #define D_PIN_DEFAULT 23
15 | #define E_PIN_DEFAULT -1 // required for 1/32 scan panels, like 64x64. Any available pin would do, i.e. IO32
16 | #define LAT_PIN_DEFAULT 5
17 | #define OE_PIN_DEFAULT 2
18 | #define CLK_PIN_DEFAULT 10
19 |
--------------------------------------------------------------------------------
/src/platforms/esp32s2/esp32s2-default-pins.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define R1_PIN_DEFAULT 45
4 | #define G1_PIN_DEFAULT 42
5 | #define B1_PIN_DEFAULT 41
6 | #define R2_PIN_DEFAULT 40
7 | #define G2_PIN_DEFAULT 39
8 | #define B2_PIN_DEFAULT 38
9 | #define A_PIN_DEFAULT 37
10 | #define B_PIN_DEFAULT 36
11 | #define C_PIN_DEFAULT 35
12 | #define D_PIN_DEFAULT 34
13 | #define E_PIN_DEFAULT -1 // required for 1/32 scan panels, like 64x64. Any available pin would do, i.e. IO32
14 | #define LAT_PIN_DEFAULT 26
15 | #define OE_PIN_DEFAULT 21
16 | #define CLK_PIN_DEFAULT 33
17 |
--------------------------------------------------------------------------------
/src/platforms/esp32s3/ESP32-S3-DevKitC-1-pin-layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/src/platforms/esp32s3/ESP32-S3-DevKitC-1-pin-layout.png
--------------------------------------------------------------------------------
/src/platforms/esp32s3/Readme.md:
--------------------------------------------------------------------------------
1 | https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/external-ram.html
2 |
3 | Restrictions
4 |
5 | External RAM use has the following restrictions:
6 |
7 | When flash cache is disabled (for example, if the flash is being written to), the external RAM also becomes inaccessible; any reads from or writes to it will lead to an illegal cache access exception. This is also the reason why ESP-IDF does not by default allocate any task stacks in external RAM (see below).
8 |
9 | External RAM cannot be used as a place to store DMA transaction descriptors or as a buffer for a DMA transfer to read from or write into. Therefore when External RAM is enabled, any buffer that will be used in combination with DMA must be allocated using heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL) and can be freed using a standard free() call.
10 |
11 | *Note, although ESP32-S3 has hardware support for DMA to/from external RAM, this is not yet supported in ESP-IDF.*
12 |
13 | External RAM uses the same cache region as the external flash. This means that frequently accessed variables in external RAM can be read and modified almost as quickly as in internal ram. However, when accessing large chunks of data (>32 KB), the cache can be insufficient, and speeds will fall back to the access speed of the external RAM. Moreover, accessing large chunks of data can “push out” cached flash, possibly making the execution of code slower afterwards.
14 |
15 | In general, external RAM will not be used as task stack memory. xTaskCreate() and similar functions will always allocate internal memory for stack and task TCBs.
16 |
17 | Reserved Pins on ESP32-S3:
18 |
19 | 
20 |
21 | Devkit Layout:
22 |
23 | 
24 |
25 |
--------------------------------------------------------------------------------
/src/platforms/esp32s3/ReservedPinsForPSRAM.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/fb3499fb66fb4941af8a818eb9be0548fe4b7a60/src/platforms/esp32s3/ReservedPinsForPSRAM.PNG
--------------------------------------------------------------------------------
/src/platforms/esp32s3/esp32s3-default-pins.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Avoid and QSPI pins
4 |
5 | #define R1_PIN_DEFAULT 4
6 | #define G1_PIN_DEFAULT 5
7 | #define B1_PIN_DEFAULT 6
8 | #define R2_PIN_DEFAULT 7
9 | #define G2_PIN_DEFAULT 15
10 | #define B2_PIN_DEFAULT 16
11 | #define A_PIN_DEFAULT 18
12 | #define B_PIN_DEFAULT 8
13 | #define C_PIN_DEFAULT 3
14 | #define D_PIN_DEFAULT 42
15 | #define E_PIN_DEFAULT -1 // required for 1/32 scan panels, like 64x64. Any available pin would do, i.e. IO32
16 | #define LAT_PIN_DEFAULT 40
17 | #define OE_PIN_DEFAULT 2
18 | #define CLK_PIN_DEFAULT 41
19 |
--------------------------------------------------------------------------------
/src/platforms/esp32s3/gdma_lcd_parallel16.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | Simple example of using the ESP32-S3's LCD peripheral for general-purpose
3 | (non-LCD) parallel data output with DMA. Connect 8 LEDs (or logic analyzer),
4 | cycles through a pattern among them at about 1 Hz.
5 | This code is ONLY for the ESP32-S3, NOT the S2, C3 or original ESP32.
6 | None of this is authoritative canon, just a lot of trial error w/datasheet
7 | and register poking. Probably more robust ways of doing this still TBD.
8 |
9 |
10 | FULL CREDIT goes to AdaFruit
11 |
12 | https://blog.adafruit.com/2022/06/21/esp32uesday-more-s3-lcd-peripheral-hacking-with-code/
13 |
14 | PLEASE SUPPORT THEM!
15 |
16 |
17 | Putin’s Russia and its genocide in Ukraine is a disgrace to humanity.
18 |
19 | https://www.reddit.com/r/ukraine/comments/xfuc6v/more_than_460_graves_have_already_been_found_in/
20 |
21 |
22 | /----------------------------------------------------------------------------
23 |
24 | */
25 |
26 | #pragma once
27 |
28 | #if __has_include ()
29 |
30 | #include
31 | #include
32 |
33 | //#include
34 | #include
35 |
36 | #include
37 | #include
38 |
39 | #include
40 | #include
41 |
42 |
43 | #include
44 | #include
45 |
46 |
47 |
48 | #include
49 | #include
50 |
51 | #include
52 |
53 | /*
54 | #if (ESP_IDF_VERSION_MAJOR == 5)
55 | #include
56 | #else
57 | #include
58 | #endif
59 | */
60 |
61 | #include
62 | #include
63 | #include
64 | #include
65 |
66 | #include
67 | #include
68 | #include
69 |
70 | #include
71 | #include
72 |
73 |
74 | #if __has_include ()
75 | #include
76 | #else
77 | #include
78 | #endif
79 |
80 | #if __has_include()
81 | #include
82 | #endif
83 |
84 | #define DMA_MAX (4096-4)
85 |
86 | // The type used for this SoC
87 | #define HUB75_DMA_DESCRIPTOR_T dma_descriptor_t
88 |
89 |
90 | //----------------------------------------------------------------------------
91 |
92 | class Bus_Parallel16
93 | {
94 | public:
95 | Bus_Parallel16()
96 | {
97 |
98 | }
99 |
100 | struct config_t
101 | {
102 | // LCD_CAM peripheral number. No need to change (only 0 for ESP32-S3.)
103 | //int port = 0;
104 |
105 | // max 40MHz (when in 16 bit / 2 byte mode)
106 | uint32_t bus_freq = 10000000;
107 | int8_t pin_wr = -1;
108 | int8_t pin_rd = -1;
109 | int8_t pin_rs = -1; // D/C
110 | bool invert_pclk = false;
111 | union
112 | {
113 | int8_t pin_data[16];
114 | struct
115 | {
116 | int8_t pin_d0;
117 | int8_t pin_d1;
118 | int8_t pin_d2;
119 | int8_t pin_d3;
120 | int8_t pin_d4;
121 | int8_t pin_d5;
122 | int8_t pin_d6;
123 | int8_t pin_d7;
124 | int8_t pin_d8;
125 | int8_t pin_d9;
126 | int8_t pin_d10;
127 | int8_t pin_d11;
128 | int8_t pin_d12;
129 | int8_t pin_d13;
130 | int8_t pin_d14;
131 | int8_t pin_d15;
132 | };
133 | };
134 | };
135 |
136 | const config_t& config(void) const { return _cfg; }
137 | void config(const config_t& config);
138 |
139 | bool init(void) ;
140 |
141 | void release(void) ;
142 |
143 | void enable_double_dma_desc();
144 | bool allocate_dma_desc_memory(size_t len);
145 |
146 | void create_dma_desc_link(void *memory, size_t size, bool dmadesc_b = false);
147 |
148 | void dma_transfer_start();
149 | void dma_transfer_stop();
150 |
151 | void flip_dma_output_buffer(int back_buffer_id);
152 |
153 | private:
154 |
155 | config_t _cfg;
156 |
157 | volatile lcd_cam_dev_t* _dev;
158 | gdma_channel_handle_t dma_chan;
159 |
160 | uint32_t _dmadesc_count = 0; // number of dma decriptors
161 |
162 | uint32_t _dmadesc_a_idx = 0;
163 | uint32_t _dmadesc_b_idx = 0;
164 |
165 | HUB75_DMA_DESCRIPTOR_T* _dmadesc_a = nullptr;
166 | HUB75_DMA_DESCRIPTOR_T* _dmadesc_b = nullptr;
167 |
168 | bool _double_dma_buffer = false;
169 |
170 | esp_lcd_i80_bus_handle_t _i80_bus = nullptr;
171 |
172 |
173 | };
174 |
175 |
176 | #endif
--------------------------------------------------------------------------------
/src/platforms/platform_detect.hpp:
--------------------------------------------------------------------------------
1 | /*----------------------------------------------------------------------------/
2 | Original Source:
3 | https://github.com/lovyan03/LovyanGFX/
4 |
5 | Licence:
6 | [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt)
7 |
8 | Author:
9 | [lovyan03](https://twitter.com/lovyan03)
10 |
11 | Contributors:
12 | [ciniml](https://github.com/ciniml)
13 | [mongonta0716](https://github.com/mongonta0716)
14 | [tobozo](https://github.com/tobozo)
15 |
16 | Modified heavily for the ESP32 HUB75 DMA library by:
17 | [mrfaptastic](https://github.com/mrfaptastic)
18 | /----------------------------------------------------------------------------*/
19 | #pragma once
20 |
21 | #if defined (ESP_PLATFORM)
22 |
23 | #include
24 |
25 | #if defined (CONFIG_IDF_TARGET_ESP32S2)
26 |
27 | //#pragma message "Compiling for ESP32-S2"
28 | #include "esp32/esp32_i2s_parallel_dma.hpp"
29 | #include "esp32s2/esp32s2-default-pins.hpp"
30 |
31 |
32 | #elif defined (CONFIG_IDF_TARGET_ESP32S3)
33 |
34 | //#pragma message "Compiling for ESP32-S3"
35 | #include "esp32s3/gdma_lcd_parallel16.hpp"
36 | #include "esp32s3/esp32s3-default-pins.hpp"
37 |
38 | #if defined(SPIRAM_FRAMEBUFFER)
39 | #pragma message "Use SPIRAM_DMA_BUFFER instead."
40 | #endif
41 |
42 | #if defined(SPIRAM_DMA_BUFFER) && defined (CONFIG_IDF_TARGET_ESP32S3)
43 | #pragma message "Enabling use of PSRAM/SPIRAM based DMA Buffer"
44 |
45 | // Disable fast functions because I don't understand the interaction with DMA PSRAM and the CPU->DMA->SPIRAM Cache implications..
46 | #define NO_FAST_FUNCTIONS 1
47 |
48 | #endif
49 |
50 | #elif defined(CONFIG_IDF_TARGET_ESP32C6)
51 |
52 | #pragma message "ESP32C6 is not supported, as this silicon does not support continuous DMA transfer."
53 |
54 | /*
55 | * Refer to: https://github.com/espressif/esp-idf/tree/master/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix
56 | * "Because of the hardware limitation in ESP32-C6 and ESP32-H2, the transaction length can't be controlled by DMA, thus
57 | * we can't flush the LED screen continuously within a hardware loop."
58 | *
59 | */
60 |
61 | //#include "esp32c6/dma_parallel_io.hpp"
62 | //#include "esp32c6/esp32c6-default-pins.hpp"
63 |
64 | #elif defined(CONFIG_IDF_TARGET_ESP32P4)
65 |
66 | #pragma message "You are ahead of your time. ESP32P4 support is planned"
67 |
68 | #elif defined (CONFIG_IDF_TARGET_ESP32) || defined(ESP32)
69 |
70 | // Assume an ESP32 (the original 2015 version)
71 | // Same include as ESP32S3
72 | //#pragma message "Compiling for original ESP32 (released 2016)"
73 |
74 | #define ESP32_THE_ORIG 1
75 | //#include "esp32/esp32_i2s_parallel_dma.hpp"
76 | //#include "esp32/esp32_i2s_parallel_dma.h"
77 | #include "esp32/esp32_i2s_parallel_dma.hpp"
78 | #include "esp32/esp32-default-pins.hpp"
79 |
80 | #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32H2)
81 |
82 | #error "ESP32 C2 C3 and H2 devices are not supported by this library."
83 |
84 |
85 | #else
86 | #error "Unknown platform."
87 |
88 | #endif
89 |
90 |
91 | #endif
92 |
93 |
--------------------------------------------------------------------------------
/testing/README.md:
--------------------------------------------------------------------------------
1 | Sample app to simulate the VirtualMatrixPanel class for testing / optimisation, without having to test with physical panels.
2 |
3 | ```
4 | g++ -o myapp.exe virtual.cpp
5 | ```
--------------------------------------------------------------------------------
/testing/baseline.hpp:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Calculate virtual->real co-ordinate mapping to underlying single chain of panels connected to ESP32.
4 | * Updates the private class member variable 'coords', so no need to use the return value.
5 | * Not thread safe, but not a concern for ESP32 sketch anyway... I think.
6 | */
7 | // DO NOT CHANGE
8 | inline VirtualCoords VirtualMatrixPanelTest::getCoords_WorkingBaslineMarch2023(int16_t virt_x, int16_t virt_y)
9 | {
10 | coords.x = coords.y = -1; // By defalt use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer
11 |
12 | if (virt_x < 0 || virt_x >= virtualResX || virt_y < 0 || virt_y >= virtualResY)
13 | { // Co-ordinates go from 0 to X-1 remember! otherwise they are out of range!
14 | return coords;
15 | }
16 |
17 | // Do we want to rotate?
18 | if (_rotate)
19 | {
20 | int16_t temp_x = virt_x;
21 | virt_x = virt_y;
22 | virt_y = virtualResY - 1 - temp_x;
23 | }
24 |
25 | int row = (virt_y / panelResY); // 0 indexed
26 | switch(panel_chain_type)
27 | {
28 |
29 | case (CHAIN_TOP_RIGHT_DOWN):
30 | {
31 | if ( (row % 2) == 1 )
32 | { // upside down panel
33 |
34 | //Serial.printf("Condition 1, row %d ", row);
35 |
36 | // refersed for the row
37 | coords.x = dmaResX - virt_x - (row*virtualResX);
38 |
39 | // y co-ord inverted within the panel
40 | coords.y = panelResY - 1 - (virt_y % panelResY);
41 |
42 |
43 | }
44 | else
45 | {
46 | //Serial.printf("Condition 2, row %d ", row);
47 |
48 | coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x;
49 | coords.y = virt_y % panelResY;
50 |
51 | }
52 |
53 | }
54 | break;
55 |
56 |
57 | case (CHAIN_TOP_LEFT_DOWN): // OK -> modulus opposite of CHAIN_TOP_RIGHT_DOWN
58 | {
59 | if ( (row % 2) == 0 )
60 | { // refersed panel
61 |
62 | //Serial.printf("Condition 1, row %d ", row);
63 | coords.x = dmaResX - virt_x - (row*virtualResX);
64 |
65 | // y co-ord inverted within the panel
66 | coords.y = panelResY - 1 - (virt_y % panelResY);
67 |
68 | }
69 | else
70 | {
71 | //Serial.printf("Condition 2, row %d ", row);
72 | coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x;
73 | coords.y = virt_y % panelResY;
74 |
75 | }
76 |
77 | }
78 | break;
79 |
80 |
81 |
82 |
83 | case (CHAIN_BOTTOM_LEFT_UP): //
84 | {
85 | row = vmodule_rows - row - 1;
86 |
87 | if ( (row % 2) == 1 )
88 | {
89 | // Serial.printf("Condition 1, row %d ", row);
90 | coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x;
91 | coords.y = virt_y % panelResY;
92 |
93 | }
94 | else
95 | { // inverted panel
96 |
97 | // Serial.printf("Condition 2, row %d ", row);
98 | coords.x = dmaResX - (row*virtualResX) - virt_x;
99 | coords.y = panelResY - 1 - (virt_y % panelResY);
100 | }
101 |
102 | }
103 | break;
104 |
105 | case (CHAIN_BOTTOM_RIGHT_UP): // OK -> modulus opposite of CHAIN_BOTTOM_LEFT_UP
106 | {
107 | row = vmodule_rows - row - 1;
108 |
109 | if ( (row % 2) == 0 )
110 | { // right side up
111 |
112 | // Serial.printf("Condition 1, row %d ", row);
113 | // refersed for the row
114 | coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x;
115 | coords.y = virt_y % panelResY;
116 |
117 | }
118 | else
119 | { // inverted panel
120 |
121 | // Serial.printf("Condition 2, row %d ", row);
122 | coords.x = dmaResX - (row*virtualResX) - virt_x;
123 | coords.y = panelResY - 1 - (virt_y % panelResY);
124 | }
125 |
126 | }
127 | break;
128 |
129 |
130 | default:
131 | return coords;
132 | break;
133 |
134 | } // end switch
135 |
136 |
137 |
138 | /* START: Pixel remapping AGAIN to convert TWO parallel scanline output that the
139 | * the underlying hardware library is designed for (because
140 | * there's only 2 x RGB pins... and convert this to 1/4 or something
141 | */
142 | if (panel_scan_rate == FOUR_SCAN_32PX_HIGH)
143 | {
144 | /* Convert Real World 'VirtualMatrixPanel' co-ordinates (i.e. Real World pixel you're looking at
145 | on the panel or chain of panels, per the chaining configuration) to a 1/8 panels
146 | double 'stretched' and 'squished' coordinates which is what needs to be sent from the
147 | DMA buffer.
148 |
149 | Note: Look at the FourScanPanel example code and you'll see that the DMA buffer is setup
150 | as if the panel is 2 * W and 0.5 * H !
151 | */
152 |
153 | if ((virt_y & 8) == 0)
154 | {
155 | coords.x += ((coords.x / panelResX) + 1) * panelResX; // 1st, 3rd 'block' of 8 rows of pixels, offset by panel width in DMA buffer
156 | }
157 | else
158 | {
159 | coords.x += (coords.x / panelResX) * panelResX; // 2nd, 4th 'block' of 8 rows of pixels, offset by panel width in DMA buffer
160 | }
161 |
162 | // http://cpp.sh/4ak5u
163 | // Real number of DMA y rows is half reality
164 | // coords.y = (y / 16)*8 + (y & 0b00000111);
165 | coords.y = (virt_y >> 4) * 8 + (virt_y & 0b00000111);
166 |
167 | }
168 | else if (panel_scan_rate == FOUR_SCAN_16PX_HIGH)
169 | {
170 | if ((virt_y & 8) == 0)
171 | {
172 | coords.x += (panelResX >> 2) * (((coords.x & 0xFFF0) >> 4) + 1); // 1st, 3rd 'block' of 8 rows of pixels, offset by panel width in DMA buffer
173 | }
174 | else
175 | {
176 | coords.x += (panelResX >> 2) * (((coords.x & 0xFFF0) >> 4)); // 2nd, 4th 'block' of 8 rows of pixels, offset by panel width in DMA buffer
177 | }
178 |
179 | if (virt_y < 32)
180 | coords.y = (virt_y >> 4) * 8 + (virt_y & 0b00000111);
181 | else
182 | {
183 | coords.y = ((virt_y - 32) >> 4) * 8 + (virt_y & 0b00000111);
184 | coords.x += 256;
185 | }
186 | }
187 |
188 | return coords;
189 | }
190 |
--------------------------------------------------------------------------------
/testing/four_scan_40_80px_hfarcan.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include // For output formatting
3 |
4 |
5 | // FOUR_SCAN_40_80PX_HFARCAN test
6 | struct Coords {
7 | int x;
8 | int y;
9 | };
10 |
11 | int main() {
12 | int panel_pixel_base = 16; // Updated pixel base
13 | Coords coords;
14 |
15 | // Header for easy Excel copying (Pipe-delimited format)
16 | std::cout << "Input X|Input Y|Output X|Output Y" << std::endl;
17 |
18 | // Loop for testing multiple inputs
19 | for (int y = 0; y < 40; y += 3) { // Updated y increment to 3
20 | for (int x = 0; x < 80; x += 10) {
21 | coords.x = x;
22 | coords.y = y;
23 |
24 | // Store original coordinates for display
25 | int input_x = coords.x;
26 | int input_y = coords.y;
27 |
28 | // Mapping logic
29 | int panel_local_x = coords.x % 80; // Compensate for chain of panels
30 |
31 | if ((((coords.y) / 10) % 2) ^ ((panel_local_x / panel_pixel_base) % 2)) {
32 | coords.x += ((coords.x / panel_pixel_base) * panel_pixel_base);
33 | } else {
34 | coords.x += (((coords.x / panel_pixel_base) + 1) * panel_pixel_base);
35 | }
36 |
37 | coords.y = (coords.y % 10) + 10 * ((coords.y / 20) % 2);
38 |
39 | // Output results in pipe-delimited format for easy Excel import
40 | std::cout << input_x << "|" << input_y << "|" << coords.x << "|" << coords.y << std::endl;
41 | }
42 | }
43 |
44 | return 0;
45 | }
--------------------------------------------------------------------------------