Skip to content

Commit

Permalink
Update to 2.0.0
Browse files Browse the repository at this point in the history
Also known as the @vortigont release! Hooray!
  • Loading branch information
mrcodetastic committed Feb 10, 2021
1 parent 6ea2280 commit 0749fa4
Show file tree
Hide file tree
Showing 43 changed files with 2,689 additions and 850 deletions.
793 changes: 531 additions & 262 deletions ESP32-HUB75-MatrixPanel-I2S-DMA.cpp

Large diffs are not rendered by default.

538 changes: 381 additions & 157 deletions ESP32-HUB75-MatrixPanel-I2S-DMA.h

Large diffs are not rendered by default.

24 changes: 16 additions & 8 deletions ESP32-VirtualMatrixPanel-I2S-DMA.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
*******************************************************************/

#include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"
#include <Fonts/FreeSansBold12pt7b.h>

#ifndef NO_GFX
#include <Fonts/FreeSansBold12pt7b.h>
#endif

struct VirtualCoords {
int16_t x;
Expand All @@ -21,8 +22,10 @@ struct VirtualCoords {

#ifdef USE_GFX_ROOT
class VirtualMatrixPanel : public GFX
#else
#elif !defined NO_GFX
class VirtualMatrixPanel : public Adafruit_GFX
#else
class VirtualMatrixPanel
#endif
{

Expand All @@ -38,11 +41,10 @@ class VirtualMatrixPanel : public Adafruit_GFX

MatrixPanel_I2S_DMA *display;

#ifdef USE_GFX_ROOT
VirtualMatrixPanel(MatrixPanel_I2S_DMA &disp, int vmodule_rows, int vmodule_cols, int panelX, int panelY, bool serpentine_chain = true, bool top_down_chain = false)
#ifdef USE_GFX_ROOT
: GFX(vmodule_cols*panelX, vmodule_rows*panelY)
#else
VirtualMatrixPanel(MatrixPanel_I2S_DMA &disp, int vmodule_rows, int vmodule_cols, int panelX, int panelY, bool serpentine_chain = true, bool top_down_chain = false )
#elif !defined NO_GFX
: Adafruit_GFX(vmodule_cols*panelX, vmodule_rows*panelY)
#endif
{
Expand Down Expand Up @@ -128,8 +130,12 @@ inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t x, int16_t y) {
// Reverse co-ordinates if panel chain from ESP starts from the TOP RIGHT
if (_chain_top_down)
{
coords.x = (this->display->width()-1) - coords.x;
coords.y = (this->display->height()-1) - coords.y;
const HUB75_I2S_CFG _cfg = this->display->getCfg();
coords.x = (_cfg.mx_width * _cfg.chain_length - 1) - coords.x;
coords.y = (_cfg.mx_height-1) - coords.y;

//coords.x = (this->display->getCfg().mx_width-1) - coords.x;
//coords.y = (this->display->getCfg().mx_height-1) - coords.y;
}

//Serial.print("Mapping to x: "); Serial.print(coords.x, DEC); Serial.print(", y: "); Serial.println(coords.y, DEC);
Expand Down Expand Up @@ -169,6 +175,7 @@ inline void VirtualMatrixPanel::drawPixelRGB24(int16_t x, int16_t y, RGB24 color
this->display->drawPixelRGB24(coords.x, coords.y, color);
}

#ifndef NO_GFX
inline void VirtualMatrixPanel::drawDisplayTest()
{
this->display->setFont(&FreeSansBold12pt7b);
Expand All @@ -183,6 +190,7 @@ inline void VirtualMatrixPanel::drawDisplayTest()
}

}
#endif

// need to recreate this one, as it wouldnt work to just map where it starts.
inline void VirtualMatrixPanel::drawIcon (int *ico, int16_t x, int16_t y, int16_t module_cols, int16_t module_rows) {
Expand Down
2 changes: 0 additions & 2 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
The MIT License (MIT)

Copyright (c) 2015 Pixelmatix

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
Expand Down
68 changes: 53 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@ This ESP32 Arduino library for HUB75 / HUB75E connector type 64x32 RGB LED 1/16

As a result, this library can theoretically provide ~16-24 bit colour, at various brightness levels without noticeable flicker.

Ones interested in internals of such matrixes could find [this article](https://www.sparkfun.com/news/2650) useful.

## Panels Supported
* 64x32 pixel 1/16 Scan LED Matrix 'Indoor' Panel, such as this [typical RGB panel available for purchase](https://www.aliexpress.com/item/256-128mm-64-32-pixels-1-16-Scan-Indoor-3in1-SMD2121-RGB-full-color-P4-led/32810362851.html).
* 64x32 (width x height) pixel 1/16 Scan LED Matrix 'Indoor' Panel, such as this [typical RGB panel available for purchase](https://www.aliexpress.com/item/256-128mm-64-32-pixels-1-16-Scan-Indoor-3in1-SMD2121-RGB-full-color-P4-led/32810362851.html).
* 64x64 pixel 1/32 Scan LED Matrix 'Indoor' Panel (experimental).
* [FM6126](FM6126A.md) / ICN2038S panels based on [this example](/examples/FM6126Panel) will also work with the correct initialisation.
* 32x16 pixel 1/4 Scan LED Matrix 'Indoor' Panel using an ingenious workaround as demonstrated in [this example](/examples/32x16_1_4_ScanPanel).
* Any of the above panel resolution / scan rates based on [FM6126](FM6126A.md) / ICN2038S chips. Refer to [this example](/examples/PatternPlasma) on how to use!

## Panel driver chips known to be working well
* ICND2012
* RUC7258
* FM6126A AKA ICN2038S, FM6124 (if specified properly)
## Panels Not Supported
* 1/4, 1/8 Scan LED Matrix Panels are not supported, please use an alternative library if you bought one of these.
* Panels with a resolution of less than 64x32pixels and/or scan rate != 1/32 or 1/16
* 1/8 Scan LED Matrix Panels are not supported, please use an alternative library if you bought one of these.

## Update for 16x32 Panels
* there is a virtual panel available to work with 16x32 panels (see: [examples/16x32 Panel](/32x16_1_4_ScanPanel). This Panel includes drawing lines and rectanges, text and scrolling text

# Installation

Expand All @@ -39,7 +48,7 @@ By default the pin mapping is as follows (defaults defined in ESP32-HUB75-Matrix
+-----------+
```

However, if you want to change this, simply provide the wanted pin mapping as part of the display.begin() call. For example, in your sketch have something like the following:
However, if you want to change this, simply provide the wanted pin mapping as part of the class initialization structure. For example, in your sketch have something like the following:

```
// Change these to whatever suits
Expand All @@ -61,8 +70,14 @@ However, if you want to change this, simply provide the wanted pin mapping as pa
#define CLK_PIN 16
display.begin(R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN ); // setup the LED matrix
HUB75_I2S_CFG::i2s_pins _pins={R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN};
HUB75_I2S_CFG mxconfig(
64, // Module width
32, // Module height
2, // chain length
_pins, // pin mapping
);
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
```

The panel must be powered by 5V AC adapter with enough current capacity. (Current varies due to how many LED are turned on at the same time. To drive all the LEDs, you need 5V4A adapter.)
Expand All @@ -79,8 +94,7 @@ MatrixPanel_I2S_DMA matrix;
void setup()
{
// MUST DO THIS FIRST!
matrix.begin(); // Use default pins supplied within ESP32-HUB75-MatrixPanel-I2S-DMA.h
// matrix.begin(R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN ); // or custom pins
matrix.begin(); // Use default values for matrix dimentions and pins supplied within ESP32-HUB75-MatrixPanel-I2S-DMA.h
// Draw a single white pixel
matrix.drawPixel(0,0, matrix.color565(255,255,255)); // can do this after .begin() only
Expand All @@ -92,6 +106,20 @@ void loop()
```

### Build-time options

Although Arduino IDE does not seem to offer any way of specifying compile-time options for external libs there are other IDE's (like PlatformIO/Eclipse) that could use that. This lib supports the following compile-time defines

**USE_GFX_ROOT** - Use lightweight version of AdafuitGFX, without Adafruit BusIO extensions


**NO_GFX** - Build without AdafuitGFX, 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 works solely with per-pixel manipulation. For example Aurora effects can work fine w/o AdafruitGFX.


**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 ;)



## Can I use with a larger panel (i.e. 64x64px square panel)?
If you want to use with a 64x64 pixel panel (typically a HUB75*E* panel) you MUST configure a valid *E_PIN* to your ESP32 and connect it to the E pin of the HUB75 panel! Hence the 'E' in 'HUB75E'
Expand All @@ -115,9 +143,9 @@ Resolutions beyond 128x128 are likely to result in crashes due to memory constra

## Panel Brightness

By default you should not need to change / set the brightness setting as the default value (16) is sufficent for most purposes. Brightness can be changed by calling `setPanelBrightness(XX)` and then `clearScreen()`.
By default you should not need to change / set the brightness setting as the default value (16) is sufficient for most purposes. Brightness can be changed by calling `setPanelBrightness(int XX)` or `setBrightness8(uint8_t XX)`.

The value to pass 'setPanelBrightness' must be a value less than MATRIX_WIDTH. For example for a single 64x32 LED Matrix Module, a value less than 64. However, if you set the brightness too high, you may experience ghosting.
The value to pass 'setPanelBrightness' must be a value less than MATRIX_CHAIN_WIDTH in pixels. For example for a single 64x32 LED Matrix Module, a value must be less than 64. However, if you set the brightness too high, you may experience ghosting.

Also you may use method `setPanelBrightness8(x)`, where x is a uint8_t value between 0-255. Library will recalculate required brightness level depending on matrix width (mostly useful with FastLED-based sketches).

Expand All @@ -126,20 +154,30 @@ Example:
```
void setup() {
Serial.begin(115200);
matrix.begin(R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN ); // setup the LED matrix
matrix.begin(); // setup the LED matrix
matrix.setPanelBrightness(16); // Set the brightness. 32 or lower ideal for a single 64x32 LED Matrix Panel.
matrix.clearScreen(); // You must clear the screen after changing brightness level for it to take effect.
// or another way
matrix.setPanelBrightness(192); // Set the brightness to about 3/4 (192/256) of maximum.
matrix.clearScreen(); // You must clear the screen after changing brightness level for it to take effect.
matrix.setPanelBrightness8(192); // Set the brightness to about 3/4 or 75% (192/256) of maximum.
}
```
Summary: setPanelBrightness(xx) value can be any number from 0 (display off) to MATRIX_WIDTH-1. So if you are chaining multiple 64x32 panels, then this value may actually be > 64 (or you will have a dim display). Changing the brightness will have a huge impact on power usage.

![It's better in real life](image.jpg)

## Latch blanking

If you face issues with image ghosting when pixels has clones with horizontal offset, than you try to change Latch blanking value. Latch blanking controls
for how many clock pulses matrix output is disabled via EO signal before/after toggling LAT signal. It hides row bits transitioning and different panels may
require longer times for proper operation. Default value is 1 clock before/after LAT row transition. This could be controlled with `MatrixPanel_I2S_DMA::setLatBlanking(uint8_t v)`. v could be between 1 to 4, default is 1, larger values won't give any benefit other than reducing brightness.


An example:
```
matrix.setLatBlanking(2);
```

## Power, Power and Power!

Having a good power supply is CRITICAL, and it is highly recommended, for chains of LED Panels to have a 2000uf capacitor soldered to the back of each LED Panel across the [GND and VCC pins](https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/39#issuecomment-720780463), otherwise you WILL run into issues with 'flashy' graphics whereby a large amount of LEDs are turned on and off in succession (due to current/power draw peaks and troughs).
Expand Down
14 changes: 6 additions & 8 deletions esp32_i2s_parallel.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "soc/i2s_struct.h"
#include "soc/i2s_reg.h"
#include "driver/periph_ctrl.h"
#include "soc/io_mux_reg.h"
#include "rom/lldesc.h"
//#include "esp_heap_caps.h"
#include "esp32_i2s_parallel.h"

Expand Down Expand Up @@ -208,18 +206,17 @@ void i2s_parallel_setup_without_malloc(i2s_dev_t *dev, const i2s_parallel_config
dev->fifo_conf.val=0;
dev->fifo_conf.rx_fifo_mod_force_en=1;
dev->fifo_conf.tx_fifo_mod_force_en=1;
//dev->fifo_conf.tx_fifo_mod=1;
dev->fifo_conf.tx_fifo_mod=1;
dev->fifo_conf.tx_fifo_mod=1; // 16-bit sigle channel mode
dev->fifo_conf.rx_data_num=32; //Thresholds.
dev->fifo_conf.tx_data_num=32;
dev->fifo_conf.dscr_en=1;
dev->fifo_conf.dscr_en=1; // FIFO will pump the data from DMA

dev->conf1.val=0;
dev->conf1.tx_stop_en=0;
dev->conf1.tx_pcm_bypass=1;

dev->conf_chan.val=0;
dev->conf_chan.tx_chan_mod=1;
dev->conf_chan.tx_chan_mod=1; // Mono
dev->conf_chan.rx_chan_mod=1;

//Invert ws to be active-low... ToDo: make this configurable
Expand All @@ -241,18 +238,19 @@ void i2s_parallel_setup_without_malloc(i2s_dev_t *dev, const i2s_parallel_config
st->dmadesc_b = cfg->lldesc_b;

//Reset FIFO/DMA -> needed? Doesn't dma_reset/fifo_reset do this?
/*
dev->lc_conf.in_rst=1; dev->lc_conf.out_rst=1; dev->lc_conf.ahbm_rst=1; dev->lc_conf.ahbm_fifo_rst=1;
dev->lc_conf.in_rst=0; dev->lc_conf.out_rst=0; dev->lc_conf.ahbm_rst=0; dev->lc_conf.ahbm_fifo_rst=0;
dev->conf.tx_reset=1; dev->conf.tx_fifo_reset=1; dev->conf.rx_fifo_reset=1;
dev->conf.tx_reset=0; dev->conf.tx_fifo_reset=0; dev->conf.rx_fifo_reset=0;
*/
// setup I2S Interrupt
SET_PERI_REG_BITS(I2S_INT_ENA_REG(1), I2S_OUT_EOF_INT_ENA_V, 1, I2S_OUT_EOF_INT_ENA_S);
// allocate a level 1 intterupt: lowest priority, as ISR isn't urgent and may take a long time to complete
esp_intr_alloc(ETS_I2S1_INTR_SOURCE, (int)(ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1), i2s_isr, NULL, NULL);

//Start dma on front buffer (buffer a)
dev->lc_conf.val=I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN;
dev->lc_conf.val=I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN;
dev->out_link.addr=((uint32_t)(&st->dmadesc_a[0]));
dev->out_link.start=1;
dev->conf.tx_start=1;
Expand Down
10 changes: 8 additions & 2 deletions esp32_i2s_parallel.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
#ifndef I2S_PARALLEL_H
#define I2S_PARALLEL_H

#if defined(ESP32)
#if defined(ESP32) || defined(IDF_VER)

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#include "driver/gpio.h"
#include "soc/i2s_struct.h"
#include "rom/lldesc.h"
#if defined(IDF_VER)
#include "esp32/rom/lldesc.h"
#elif defined(ESP32)
#include "rom/lldesc.h"
#endif


#define DMA_MAX (4096-4)
//#define DMA_MAX (512)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
// Example sketch which shows how to display some patterns
// on a 64x32 LED matrix
//

#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
MatrixPanel_I2S_DMA dma_display;

// Or use an Alternative non-DMA library, i.e:
//#include <P3RGB64x32MatrixPanel.h>
//P3RGB64x32MatrixPanel display;
/*
* Below is an example of the 'legacy' way of initialising the MatrixPanel_I2S_DMA class.
* i.e. Matrix Width and Height will need to be confirmed as compile-time directives.
* By default the library assumes a single 64x32 pixel panel is connected.
*
* Refer to the example '2_PatternPlasma' on the new / correct way to setup this library
* for different resolutions / panel chain lengths.
*
*/
MatrixPanel_I2S_DMA dma_display;

// Or use an Alternative non-DMA library, i.e:
//#include <P3RGB64x32MatrixPanel.h>
//P3RGB64x32MatrixPanel display;


void setup() {
Expand Down Expand Up @@ -94,26 +108,6 @@ void setup() {
dma_display.setTextColor(dma_display.color444(15,0,8));
dma_display.println("*");

delay(2000);
/*
for (int i = 15; i > 0; i--)
{
// fade out
dma_display.fillScreen(dma_display.color565(0, 0, i*17));
delay(250);
}
for (int i = 15; i > 0; i--)
{
// draw a blue circle
dma_display.drawCircle(10, 10, 10, dma_display.color565(i*17, 0, 0));
delay(250);
}
*/



// whew!
}

void loop() {
Expand Down
Loading

0 comments on commit 0749fa4

Please sign in to comment.