Fix some typos
This commit is contained in:
parent
cf66382d75
commit
7ed06c1217
33 changed files with 105 additions and 105 deletions
|
@ -60,7 +60,7 @@
|
||||||
Then we ask the I2S-parallel driver to set up a DMA chain so the subframes are sent out in a sequence that satisfies the requirement that
|
Then we ask the I2S-parallel driver to set up a DMA chain so the subframes are sent out in a sequence that satisfies the requirement that
|
||||||
subframe x has to be sent out for (2^x) ticks. Finally, we fill the subframes with image data.
|
subframe x has to be sent out for (2^x) ticks. Finally, we fill the subframes with image data.
|
||||||
|
|
||||||
We use a front buffer/back buffer technique here to make sure the display is refreshed in one go and drawing artifacts do not reach the display.
|
We use a front buffer/back buffer technique here to make sure the display is refreshed in one go and drawing artefacts do not reach the display.
|
||||||
In practice, for small displays this is not really necessarily.
|
In practice, for small displays this is not really necessarily.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -327,7 +327,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// first set of data is LSB through MSB, single pass (IF TOTAL SIZE < DMA_MAX) - all color bits are displayed once, which takes care of everything below and inlcluding LSBMSB_TRANSITION_BIT
|
// first set of data is LSB through MSB, single pass (IF TOTAL SIZE < DMA_MAX) - all color bits are displayed once, which takes care of everything below and including LSBMSB_TRANSITION_BIT
|
||||||
// NOTE: size must be less than DMA_MAX - worst case for library: 16-bpp with 256 pixels per row would exceed this, need to break into two
|
// NOTE: size must be less than DMA_MAX - worst case for library: 16-bpp with 256 pixels per row would exceed this, need to break into two
|
||||||
link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, dma_buff.rowBits[row]->getDataPtr(), dma_buff.rowBits[row]->size(num_dma_payload_color_depths));
|
link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, dma_buff.rowBits[row]->getDataPtr(), dma_buff.rowBits[row]->size(num_dma_payload_color_depths));
|
||||||
previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
||||||
|
@ -342,12 +342,12 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
||||||
if ( rowBitStructBuffSize > DMA_MAX )
|
if ( rowBitStructBuffSize > DMA_MAX )
|
||||||
{
|
{
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.printf_P(PSTR("Spliting DMA payload for %d color depths into %d byte payloads.\r\n"), PIXEL_COLOR_DEPTH_BITS-1, rowBitStructBuffSize/PIXEL_COLOR_DEPTH_BITS );
|
Serial.printf_P(PSTR("Splitting DMA payload for %d color depths into %d byte payloads.\r\n"), PIXEL_COLOR_DEPTH_BITS-1, rowBitStructBuffSize/PIXEL_COLOR_DEPTH_BITS );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (int cd = 1; cd < PIXEL_COLOR_DEPTH_BITS; cd++)
|
for (int cd = 1; cd < PIXEL_COLOR_DEPTH_BITS; cd++)
|
||||||
{
|
{
|
||||||
// first set of data is LSB through MSB, single pass - all color bits are displayed once, which takes care of everything below and inlcluding LSBMSB_TRANSITION_BIT
|
// first set of data is LSB through MSB, single pass - all color bits are displayed once, which takes care of everything below and including LSBMSB_TRANSITION_BIT
|
||||||
// TODO: size must be less than DMA_MAX - worst case for library: 16-bpp with 256 pixels per row would exceed this, need to break into two
|
// TODO: size must be less than DMA_MAX - worst case for library: 16-bpp with 256 pixels per row would exceed this, need to break into two
|
||||||
link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, dma_buff.rowBits[row]->getDataPtr(cd, 0), dma_buff.rowBits[row]->size(num_dma_payload_color_depths) );
|
link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, dma_buff.rowBits[row]->getDataPtr(cd, 0), dma_buff.rowBits[row]->size(num_dma_payload_color_depths) );
|
||||||
previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
||||||
|
@ -441,7 +441,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
||||||
|
|
||||||
/* There are 'bits' set in the frameStruct that we simply don't need to set every single time we change a pixel / DMA buffer co-ordinate.
|
/* There are 'bits' set in the frameStruct that we simply don't need to set every single time we change a pixel / DMA buffer co-ordinate.
|
||||||
* For example, the bits that determine the address lines, we don't need to set these every time. Once they're in place, and assuming we
|
* For example, the bits that determine the address lines, we don't need to set these every time. Once they're in place, and assuming we
|
||||||
* don't accidently clear them, then we don't need to set them again.
|
* don't accidentally clear them, then we don't need to set them again.
|
||||||
* So to save processing, we strip this logic out to the absolute bare minimum, which is toggling only the R,G,B pixels (bits) per co-ord.
|
* So to save processing, we strip this logic out to the absolute bare minimum, which is toggling only the R,G,B pixels (bits) per co-ord.
|
||||||
*
|
*
|
||||||
* Critical dependency: That 'updateMatrixDMABuffer(uint8_t red, uint8_t green, uint8_t blue)' has been run at least once over the
|
* Critical dependency: That 'updateMatrixDMABuffer(uint8_t red, uint8_t green, uint8_t blue)' has been run at least once over the
|
||||||
|
@ -538,7 +538,7 @@ void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16
|
||||||
ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(y_coord, color_depth_idx, back_buffer_id);
|
ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(y_coord, color_depth_idx, back_buffer_id);
|
||||||
|
|
||||||
|
|
||||||
// We need to update the correct uint16_t word in the rowBitStruct array poiting to a specific pixel at X - coordinate
|
// We need to update the correct uint16_t word in the rowBitStruct array pointing to a specific pixel at X - coordinate
|
||||||
p[x_coord] &= _colorbitclear; // reset RGB bits
|
p[x_coord] &= _colorbitclear; // reset RGB bits
|
||||||
p[x_coord] |= RGB_output_bits; // set new RGB bits
|
p[x_coord] |= RGB_output_bits; // set new RGB bits
|
||||||
|
|
||||||
|
@ -604,7 +604,7 @@ void MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - clears and reinitializes color/control data in DMA buffs
|
* @brief - clears and reinitializes color/control data in DMA buffs
|
||||||
* When allocated, DMA buffs might be dirtry, so we need to blank it and initialize ABCDE,LAT,OE control bits.
|
* When allocated, DMA buffs might be dirty, so we need to blank it and initialize ABCDE,LAT,OE control bits.
|
||||||
* Those control bits are constants during the entire DMA sweep and never changed when updating just pixel color data
|
* Those control bits are constants during the entire DMA sweep and never changed when updating just pixel color data
|
||||||
* so we could set it once on DMA buffs initialization and forget.
|
* so we could set it once on DMA buffs initialization and forget.
|
||||||
* This effectively clears buffers to blank BLACK and makes it ready to display output.
|
* This effectively clears buffers to blank BLACK and makes it ready to display output.
|
||||||
|
@ -834,7 +834,7 @@ uint8_t MatrixPanel_I2S_DMA::setLatBlanking(uint8_t pulses){
|
||||||
pulses = DEFAULT_LAT_BLANKING;
|
pulses = DEFAULT_LAT_BLANKING;
|
||||||
|
|
||||||
m_cfg.latch_blanking = pulses;
|
m_cfg.latch_blanking = pulses;
|
||||||
setPanelBrightness(brightness); // set brighness to reset OE bits to the values matching new LAT blanking setting
|
setPanelBrightness(brightness); // set brightness to reset OE bits to the values matching new LAT blanking setting
|
||||||
return m_cfg.latch_blanking;
|
return m_cfg.latch_blanking;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,7 +979,7 @@ void MatrixPanel_I2S_DMA::vlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
uint16_t _colorbitclear = BITMASK_RGB1_CLEAR;
|
uint16_t _colorbitclear = BITMASK_RGB1_CLEAR;
|
||||||
do { // iterate pixels in a column
|
do { // iterate pixels in a column
|
||||||
|
|
||||||
if (_y >= ROWS_PER_FRAME){ // if y-coord overlaped bottom-half panel
|
if (_y >= ROWS_PER_FRAME){ // if y-coord overlapped bottom-half panel
|
||||||
_y -= ROWS_PER_FRAME;
|
_y -= ROWS_PER_FRAME;
|
||||||
_colorbitclear = BITMASK_RGB2_CLEAR;
|
_colorbitclear = BITMASK_RGB2_CLEAR;
|
||||||
RGB_output_bits <<= BITS_RGB2_OFFSET;
|
RGB_output_bits <<= BITS_RGB2_OFFSET;
|
||||||
|
@ -999,7 +999,7 @@ void MatrixPanel_I2S_DMA::vlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - update DMA buff drawing a rectangular at specified coordinates
|
* @brief - update DMA buff drawing a rectangular at specified coordinates
|
||||||
* this works much faster than mulltiple consecutive per-pixel calls to updateMatrixDMABuffer()
|
* this works much faster than multiple consecutive per-pixel calls to updateMatrixDMABuffer()
|
||||||
* @param int16_t x, int16_t y - coordinates of a top-left corner
|
* @param int16_t x, int16_t y - coordinates of a top-left corner
|
||||||
* @param int16_t w, int16_t h - width and height of a rectangular, min is 1 px
|
* @param int16_t w, int16_t h - width and height of a rectangular, min is 1 px
|
||||||
* @param uint8_t r - RGB888 color
|
* @param uint8_t r - RGB888 color
|
||||||
|
|
|
@ -176,7 +176,7 @@
|
||||||
#error "Pixel color depth bits cannot be less than 2."
|
#error "Pixel color depth bits cannot be less than 2."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This library is designed to take an 8 bit / 1 byt value (0-255) for each R G B colour sub-pixel.
|
/* This library is designed to take an 8 bit / 1 byte value (0-255) for each R G B colour sub-pixel.
|
||||||
* The PIXEL_COLOR_DEPTH_BITS should always be '8' as a result.
|
* The PIXEL_COLOR_DEPTH_BITS should always be '8' as a result.
|
||||||
* However, if the library is to be used with lower colour depth (i.e. 6 bit colour), then we need to ensure the 8-bit value passed to the colour masking
|
* However, if the library is to be used with lower colour depth (i.e. 6 bit colour), then we need to ensure the 8-bit value passed to the colour masking
|
||||||
* is adjusted accordingly to ensure the LSB's are shifted left to MSB, by the difference. Otherwise the colours will be all screwed up.
|
* is adjusted accordingly to ensure the LSB's are shifted left to MSB, by the difference. Otherwise the colours will be all screwed up.
|
||||||
|
@ -187,7 +187,7 @@ static constexpr uint8_t const MASK_OFFSET = 8-PIXEL_COLOR_DEPTH_BITS;
|
||||||
|
|
||||||
/***************************************************************************************/
|
/***************************************************************************************/
|
||||||
|
|
||||||
/** @brief - Structure holds raw DMA data to drive TWO full rows of pixels spaning through all chained modules
|
/** @brief - Structure holds raw DMA data to drive TWO full rows of pixels spanning through all chained modules
|
||||||
* Note: sizeof(data) must be multiple of 32 bits, as ESP32 DMA linked list buffer address pointer must be word-aligned
|
* Note: sizeof(data) must be multiple of 32 bits, as ESP32 DMA linked list buffer address pointer must be word-aligned
|
||||||
*/
|
*/
|
||||||
struct rowBitStruct {
|
struct rowBitStruct {
|
||||||
|
@ -206,7 +206,7 @@ struct rowBitStruct {
|
||||||
*/
|
*/
|
||||||
size_t size(uint8_t _dpth=0 ) { if (!_dpth) _dpth = color_depth; return width * _dpth * sizeof(ESP32_I2S_DMA_STORAGE_TYPE); };
|
size_t size(uint8_t _dpth=0 ) { if (!_dpth) _dpth = color_depth; return width * _dpth * sizeof(ESP32_I2S_DMA_STORAGE_TYPE); };
|
||||||
|
|
||||||
/** @brief - returns pointer to the row's data vector begining at pixel[0] for _dpth color bit
|
/** @brief - returns pointer to the row's data vector beginning at pixel[0] for _dpth color bit
|
||||||
* default - returns pointer to the data vector's head
|
* default - returns pointer to the data vector's head
|
||||||
* NOTE: this call might be very slow in loops. Due to poor instruction caching in esp32 it might be required a reread from flash
|
* NOTE: this call might be very slow in loops. Due to poor instruction caching in esp32 it might be required a reread from flash
|
||||||
* every loop cycle, better use inlined #define instead in such cases
|
* every loop cycle, better use inlined #define instead in such cases
|
||||||
|
@ -264,7 +264,7 @@ struct HUB75_I2S_CFG {
|
||||||
|
|
||||||
// physical width of a single matrix panel module (in pixels, usually it is 64 ;) )
|
// physical width of a single matrix panel module (in pixels, usually it is 64 ;) )
|
||||||
uint16_t mx_width;
|
uint16_t mx_width;
|
||||||
// physical height of a single matrix panel module (in pixels, usually amost always it is either 32 or 64)
|
// physical height of a single matrix panel module (in pixels, usually almost always it is either 32 or 64)
|
||||||
uint16_t mx_height;
|
uint16_t mx_height;
|
||||||
// number of chained panels regardless of the topology, default 1 - a single matrix module
|
// number of chained panels regardless of the topology, default 1 - a single matrix module
|
||||||
uint16_t chain_length;
|
uint16_t chain_length;
|
||||||
|
@ -316,7 +316,7 @@ struct HUB75_I2S_CFG {
|
||||||
shift_driver _drv = SHIFTREG,
|
shift_driver _drv = SHIFTREG,
|
||||||
bool _dbuff = false,
|
bool _dbuff = false,
|
||||||
clk_speed _i2sspeed = HZ_10M,
|
clk_speed _i2sspeed = HZ_10M,
|
||||||
uint8_t _latblk = 1, // Anything > 1 seems to cause artifacts on ICS panels
|
uint8_t _latblk = 1, // Anything > 1 seems to cause artefacts on ICS panels
|
||||||
bool _clockphase = true,
|
bool _clockphase = true,
|
||||||
uint8_t _min_refresh_rate = 85
|
uint8_t _min_refresh_rate = 85
|
||||||
) : mx_width(_w),
|
) : mx_width(_w),
|
||||||
|
@ -347,7 +347,7 @@ class MatrixPanel_I2S_DMA {
|
||||||
/**
|
/**
|
||||||
* MatrixPanel_I2S_DMA
|
* MatrixPanel_I2S_DMA
|
||||||
*
|
*
|
||||||
* default predefined values are used for matrix configuraton
|
* default predefined values are used for matrix configuration
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
MatrixPanel_I2S_DMA()
|
MatrixPanel_I2S_DMA()
|
||||||
|
@ -372,7 +372,7 @@ class MatrixPanel_I2S_DMA {
|
||||||
#endif
|
#endif
|
||||||
m_cfg(opts) {}
|
m_cfg(opts) {}
|
||||||
|
|
||||||
/* Propagate the DMA pin configuration, allocate DMA buffs and start data ouput, initialy blank */
|
/* Propagate the DMA pin configuration, allocate DMA buffs and start data output, initially blank */
|
||||||
bool begin(){
|
bool begin(){
|
||||||
|
|
||||||
if (initialized) return true; // we don't do this twice or more!
|
if (initialized) return true; // we don't do this twice or more!
|
||||||
|
@ -477,7 +477,7 @@ class MatrixPanel_I2S_DMA {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - override Adafruit's fillRect
|
* @brief - override Adafruit's fillRect
|
||||||
* this works much faster than mulltiple consecutive per-pixel drawPixel() calls
|
* this works much faster than multiple consecutive per-pixel drawPixel() calls
|
||||||
*/
|
*/
|
||||||
virtual void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
|
virtual void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
|
||||||
uint8_t r, g, b;
|
uint8_t r, g, b;
|
||||||
|
@ -595,7 +595,7 @@ class MatrixPanel_I2S_DMA {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - clears and reinitializes color/control data in DMA buffs
|
* @brief - clears and reinitializes color/control data in DMA buffs
|
||||||
* When allocated, DMA buffs might be dirtry, so we need to blank it and initialize ABCDE,LAT,OE control bits.
|
* When allocated, DMA buffs might be dirty, so we need to blank it and initialize ABCDE,LAT,OE control bits.
|
||||||
* Those control bits are constants during the entire DMA sweep and never changed when updating just pixel color data
|
* Those control bits are constants during the entire DMA sweep and never changed when updating just pixel color data
|
||||||
* so we could set it once on DMA buffs initialization and forget.
|
* so we could set it once on DMA buffs initialization and forget.
|
||||||
* This effectively clears buffers to blank BLACK and makes it ready to display output.
|
* This effectively clears buffers to blank BLACK and makes it ready to display output.
|
||||||
|
@ -643,7 +643,7 @@ class MatrixPanel_I2S_DMA {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - update DMA buff drawing a rectangular at specified coordinates
|
* @brief - update DMA buff drawing a rectangular at specified coordinates
|
||||||
* uses Fast H/V line draw internally, works faster than mulltiple consecutive pixel by pixel calls to updateMatrixDMABuffer()
|
* uses Fast H/V line draw internally, works faster than multiple consecutive pixel by pixel calls to updateMatrixDMABuffer()
|
||||||
* @param int16_t x, int16_t y - coordinates of a top-left corner
|
* @param int16_t x, int16_t y - coordinates of a top-left corner
|
||||||
* @param int16_t w, int16_t h - width and height of a rectangular, min is 1 px
|
* @param int16_t w, int16_t h - width and height of a rectangular, min is 1 px
|
||||||
* @param uint8_t r - RGB888 color
|
* @param uint8_t r - RGB888 color
|
||||||
|
@ -683,7 +683,7 @@ class MatrixPanel_I2S_DMA {
|
||||||
* (two rows of pixels are refreshed in parallel)
|
* (two rows of pixels are refreshed in parallel)
|
||||||
* Memory is allocated (malloc'd) by the row, and not in one massive chunk, for flexibility.
|
* Memory is allocated (malloc'd) by the row, and not in one massive chunk, for flexibility.
|
||||||
* The whole DMA framebuffer is just a vector of pointers to structs with ESP32_I2S_DMA_STORAGE_TYPE arrays
|
* The whole DMA framebuffer is just a vector of pointers to structs with ESP32_I2S_DMA_STORAGE_TYPE arrays
|
||||||
* Since it's dimensions is unknown prior to class initialization, we just decrale it here as empty struct and will do all allocations later.
|
* Since it's dimensions is unknown prior to class initialization, we just declare it here as empty struct and will do all allocations later.
|
||||||
* Refer to rowBitStruct to get the idea of it's internal structure
|
* Refer to rowBitStruct to get the idea of it's internal structure
|
||||||
*/
|
*/
|
||||||
frameStruct dma_buff;
|
frameStruct dma_buff;
|
||||||
|
|
|
@ -214,7 +214,7 @@ inline void VirtualMatrixPanel::drawDisplayTest()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// need to recreate this one, as it wouldnt work to just map where it starts.
|
// need to recreate this one, as it wouldn't work to just map where it starts.
|
||||||
inline void VirtualMatrixPanel::drawIcon (int *ico, int16_t x, int16_t y, int16_t icon_cols, int16_t icon_rows) {
|
inline void VirtualMatrixPanel::drawIcon (int *ico, int16_t x, int16_t y, int16_t icon_cols, int16_t icon_rows) {
|
||||||
int i, j;
|
int i, j;
|
||||||
for (i = 0; i < icon_rows; i++) {
|
for (i = 0; i < icon_rows; i++) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ This ESP32 Arduino/IDF library for HUB75 / HUB75E connector type 64x32 RGB LED 1
|
||||||
- **CIE 1931** luminance [correction](https://ledshield.wordpress.com/2012/11/13/led-brightness-to-your-eye-gamma-correction-no/) (aka natural LED dimming)
|
- **CIE 1931** luminance [correction](https://ledshield.wordpress.com/2012/11/13/led-brightness-to-your-eye-gamma-correction-no/) (aka natural LED dimming)
|
||||||
- **Adafruit GFX API** - library could be build with AdafruitGFX, simplified GFX or without GFX API at all
|
- **Adafruit GFX API** - library could be build with AdafruitGFX, simplified GFX or without GFX API at all
|
||||||
|
|
||||||
If you wanna ask "*...OK, OK, than whats the price for those features?*" I'll tell you - "[memory](/doc/i2s_memcalc.md), you pay it all by precious MCU's memory for DMA buffer".
|
If you wanna ask "*...OK, OK, than what's the price for those features?*" I'll tell you - "[memory](/doc/i2s_memcalc.md), you pay it all by precious MCU's memory for DMA buffer".
|
||||||
|
|
||||||
## ESP32 Supported
|
## ESP32 Supported
|
||||||
Espressif have kept the 'ESP32' name for all their chips for brand recognition, but their new variant MCU's are different to the ESP32 this library was built for.
|
Espressif have kept the 'ESP32' name for all their chips for brand recognition, but their new variant MCU's are different to the ESP32 this library was built for.
|
||||||
|
@ -52,7 +52,7 @@ RISC-V ESP32's (like the C3) are not, and will never be supported as they do no
|
||||||
* 32x16 pixel 1/4 Scan LED Matrix 'Indoor' Panel using an ingenious workaround as demonstrated in the 32x16_1_4_ScanPanel example.
|
* 32x16 pixel 1/4 Scan LED Matrix 'Indoor' Panel using an ingenious workaround as demonstrated in the 32x16_1_4_ScanPanel example.
|
||||||
* 126x64 [SM5266P](https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/164) 1/32 Scan Panel
|
* 126x64 [SM5266P](https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/164) 1/32 Scan Panel
|
||||||
|
|
||||||
Ones interested in internals of such matrixes could find [this article](https://www.sparkfun.com/news/2650) useful.
|
Ones interested in internals of such matrices could find [this article](https://www.sparkfun.com/news/2650) useful.
|
||||||
|
|
||||||
Due to the high-speed optimized nature of this library, only specific panels are supported. Please do not raise issues with respect to panels not supported on the list below.
|
Due to the high-speed optimized nature of this library, only specific panels are supported. Please do not raise issues with respect to panels not supported on the list below.
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ Due to the high-speed optimized nature of this library, only specific panels are
|
||||||
Please use an [alternative library](https://github.com/2dom/PxMatrix) if you bought one of these.
|
Please use an [alternative library](https://github.com/2dom/PxMatrix) if you bought one of these.
|
||||||
|
|
||||||
## Update for 16x32 Panels
|
## Update for 16x32 Panels
|
||||||
* There is a virtual panel class available to work with 16x32 panels (see: [examples/16x32 Panel](/examples/P6_32x16_1_4_ScanPanel). This Panel includes drawing lines and rectanges, text and scrolling text
|
* There is a virtual panel class available to work with 16x32 panels (see: [examples/16x32 Panel](/examples/P6_32x16_1_4_ScanPanel). This Panel includes drawing lines and rectangles, text and scrolling text
|
||||||
|
|
||||||
## Cool uses of this library
|
## Cool uses of this library
|
||||||
There are a number of great looking LED graphical display projects which leverage this library, these include:
|
There are a number of great looking LED graphical display projects which leverage this library, these include:
|
||||||
|
@ -149,7 +149,7 @@ Once this is working, refer to the [PIO Test Patterns](/examples/PIO_TestPattern
|
||||||
>Note: Requires the use of [PlatformIO](https://platformio.org/), which you should probably use if you aren't already.
|
>Note: Requires the use of [PlatformIO](https://platformio.org/), which you should probably use if you aren't already.
|
||||||
# More Information
|
# More Information
|
||||||
## Build-time options
|
## Build-time options
|
||||||
Although Arduino IDE does not [seem](https://github.com/arduino/Arduino/issues/421) to offer any way of specifying compile-time options for external libs there are other IDE's (like [PlatformIO](https://platformio.org/)/[Eclipse](https://www.eclipse.org/ide/)) that could use that. Check [Buld Options](doc/BuildOptions.md) document for reference.
|
Although Arduino IDE does not [seem](https://github.com/arduino/Arduino/issues/421) to offer any way of specifying compile-time options for external libs there are other IDE's (like [PlatformIO](https://platformio.org/)/[Eclipse](https://www.eclipse.org/ide/)) that could use that. Check [Build Options](doc/BuildOptions.md) document for reference.
|
||||||
|
|
||||||
## Memory constraints
|
## Memory constraints
|
||||||
If you are going to use large/combined panels make sure to check for [memory constraints](/doc/i2s_memcalc.md).
|
If you are going to use large/combined panels make sure to check for [memory constraints](/doc/i2s_memcalc.md).
|
||||||
|
|
|
@ -21,11 +21,11 @@ build_flags =
|
||||||
| **SERIAL_DEBUG** |Print out detailed information about memory allocations, DMA descriptors setup and color depth [BCM](http://www.batsocks.co.uk/readme/art_bcm_5.htm) |
|
| **SERIAL_DEBUG** |Print out detailed information about memory allocations, DMA descriptors setup and color depth [BCM](http://www.batsocks.co.uk/readme/art_bcm_5.htm) |
|
||||||
| **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|
|
| **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|
|
||||||
| **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. |
|
| **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. |
|
||||||
| **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 eather|
|
| **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|
|
||||||
|**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). Normaly library would adjust every pixel's RGB888 so that liminance (or brighness control) for the corresponding LED's would apper '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). Normaly you would like to keep this enabled by default. Not only it makes brightness control "linear", it also makes colors more vivid, otherwise it looks brighter but 'bleached'.|You might want to turn it off in some special cases like: <ul><li>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).<li>running at low color depth's - it **might** (or might not) look better in shadows, darker gradients w/o compensation, try it<li>you run for as bright output as possible, no matter what (make sure you have proper powering)<li>you run for speed/save resources at all costs</ul> |
|
|**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 colors more vivid, otherwise it looks brighter but 'bleached'.|You might want to turn it off in some special cases like: <ul><li>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).<li>running at low color depth's - it **might** (or might not) look better in shadows, darker gradients w/o compensation, try it<li>you run for as bright output as possible, no matter what (make sure you have proper powering)<li>you run for speed/save resources at all costs</ul> |
|
||||||
|
|
||||||
## Build-time variables
|
## Build-time variables
|
||||||
|
|
||||||
| Flag | Description | Note |
|
| Flag | Description | Note |
|
||||||
| :------------ |---------------|-----|
|
| :------------ |---------------|-----|
|
||||||
| **PIXEL_COLOR_DEPTH_BITS=8** | Color depth per color per pixel in range 2-8. More bit's - more natural color. But on the other hand every additional bit:<ul><li>eats ~2.5 bits of DMA memoy per pixel<li>reduces matrix refresh rate in power of two due to nature of [BCM](http://www.batsocks.co.uk/readme/art_bcm_5.htm)</ul> | Default is 8 bits per color per pixel, i.e. TrueColor 24 bit RGB. For higher resolutions, from 64x64 and above it is not possible to provide full 24 bits color 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 humans eye actually. Refer to the [I2S memcalc](i2s_memcalc.md) for more details|
|
| **PIXEL_COLOR_DEPTH_BITS=8** | Color depth per color per pixel in range 2-8. More bit's - more natural color. But on the other hand every additional bit:<ul><li>eats ~2.5 bits of DMA memory per pixel<li>reduces matrix refresh rate in power of two due to nature of [BCM](http://www.batsocks.co.uk/readme/art_bcm_5.htm)</ul> | Default is 8 bits per color per pixel, i.e. TrueColor 24 bit RGB. For higher resolutions, from 64x64 and above it is not possible to provide full 24 bits color 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 humans eye actually. Refer to the [I2S memcalc](i2s_memcalc.md) for more details|
|
|
@ -1,13 +1,13 @@
|
||||||
## Estimating fillrate
|
## Estimating fillrate
|
||||||
|
|
||||||
Here are some results of simple tests on filling DMA buffer with data.
|
Here are some results of simple tests on filling DMA buffer with data.
|
||||||
Filling DMA buffer requres lot's 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.
|
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.
|
||||||
I've done this while optimizing loops and bit logic along with testing compiler results.
|
I've done this while optimizing loops and bit logic along with testing compiler results.
|
||||||
|
|
||||||
So the testbed is:
|
So the testbed is:
|
||||||
- Matrix modules: 4 x FM6126A based 64x64 modules chained in 256x64
|
- Matrix modules: 4 x FM6126A based 64x64 modules chained in 256x64
|
||||||
|
|
||||||
A testpatters sketch:
|
A testpatterns sketch:
|
||||||
- allocating single DMA buffs for 256x64
|
- allocating single DMA buffs for 256x64
|
||||||
- allocating (NUM_LEDS*3) bytes for CRGB buffer
|
- allocating (NUM_LEDS*3) bytes for CRGB buffer
|
||||||
- measuring microseconds for the following calls:
|
- measuring microseconds for the following calls:
|
||||||
|
@ -19,7 +19,7 @@ A testpatters sketch:
|
||||||
- drawing lines
|
- drawing lines
|
||||||
|
|
||||||
|
|
||||||
||clearScreen()|drawPixelRGB888(), ticks|fillScreen()|fillScreen with a drawPixel()|fillRect() over Maxrix|V-line with drawPixel|fast-V-line|H-line with drawPixel|fast-H-line|
|
||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|
|
||||||
|--|--|--|--|--|--|--|--|--|--|
|
|--|--|--|--|--|--|--|--|--|--|
|
||||||
|v1.2.4|1503113 ticks|9244 non-cached, 675 cached|1719 us, 412272 t|47149 us, 11315418 ticks|-|24505 us, 5880209 ticks|-|24200 us|-|
|
|v1.2.4|1503113 ticks|9244 non-cached, 675 cached|1719 us, 412272 t|47149 us, 11315418 ticks|-|24505 us, 5880209 ticks|-|24200 us|-|
|
||||||
|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|
|
|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|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
### I2S HUB75 Calculator
|
### I2S HUB75 Calculator
|
||||||
|
|
||||||
I've made this [spreadsheet](i2s_memcalc.xlsm) to estimate all of the main parameters for ESP32-HUB75-MatrixPanel-I2S-DMA lib driving any combination of matrixes/chains so that I do not need to reflash it hundreds of times just to check for the debug info about memory.
|
I've made this [spreadsheet](i2s_memcalc.xlsm) to estimate all of the main parameters for ESP32-HUB75-MatrixPanel-I2S-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.
|
||||||
Be sure to enable embeded macro's to allow refresh rate calculations.
|
Be sure to enable embedded macro's to allow refresh rate calculations.
|
||||||
|
|
||||||
![](i2scalc.png)
|
![](i2scalc.png)
|
||||||
Just fill-in all of the INPUT fields and get the OUTPUTs.
|
Just fill-in all of the INPUT fields and get the OUTPUTs.
|
||||||
|
@ -32,9 +32,9 @@ There are 3 parameters you can choose from (actually two:)
|
||||||
|
|
||||||
- I2S clock speed - run-time tunable with a very limited options
|
- I2S clock speed - run-time tunable with a very limited options
|
||||||
|
|
||||||
- **LSB-to-MSB** transition - it can't be controlled in any way, library uses it internaly trying to balance all of the above
|
- **LSB-to-MSB** transition - it can't be controlled in any way, library uses it internally trying to balance all of the above
|
||||||
|
|
||||||
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 overal color depth. **But** reducing global color depth would also save lot's of precious RAM!
|
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!
|
||||||
Now it's all up to you to decide :)
|
Now it's all up to you to decide :)
|
||||||
|
|
||||||
/Vortigont/
|
/Vortigont/
|
||||||
|
|
|
@ -295,7 +295,7 @@ esp_err_t i2s_parallel_driver_install(i2s_port_t port, i2s_parallel_config_t* co
|
||||||
dev->fifo_conf.tx_fifo_mod = 3;
|
dev->fifo_conf.tx_fifo_mod = 3;
|
||||||
} else {
|
} else {
|
||||||
// Mode 1, single 16-bit channel, load 16 bit sample(*) into fifo and pad to 32 bit with zeros
|
// Mode 1, single 16-bit channel, load 16 bit sample(*) into fifo and pad to 32 bit with zeros
|
||||||
// *Actually a 32 bit read where two samples are read at once. Length of fifo must thus still be word-alligned
|
// *Actually a 32 bit read where two samples are read at once. Length of fifo must thus still be word-aligned
|
||||||
dev->fifo_conf.tx_fifo_mod = 1;
|
dev->fifo_conf.tx_fifo_mod = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
#include <esp_err.h>
|
#include <esp_err.h>
|
||||||
|
|
||||||
// Turn on and off a periphal
|
// Turn on and off a peripheral
|
||||||
#include <driver/periph_ctrl.h>
|
#include <driver/periph_ctrl.h>
|
||||||
|
|
||||||
// GPIO
|
// GPIO
|
||||||
|
@ -227,7 +227,7 @@ esp_err_t i2s_parallel_driver_install(i2s_port_t port, i2s_parallel_config_t* cf
|
||||||
|
|
||||||
// setup I2S Interrupt
|
// 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);
|
// 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
|
// allocate a level 1 interrupt: 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), gdma_irq_handler, NULL, NULL);
|
esp_intr_alloc(ETS_I2S1_INTR_SOURCE, (int)(ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1), gdma_irq_handler, NULL, NULL);
|
||||||
GDMA.intr[0].ena.out_eof = 1; //?
|
GDMA.intr[0].ena.out_eof = 1; //?
|
||||||
|
@ -243,7 +243,7 @@ esp_err_t i2s_parallel_driver_install(i2s_port_t port, i2s_parallel_config_t* cf
|
||||||
// Setup interrupt
|
// Setup interrupt
|
||||||
|
|
||||||
// Setup outlink
|
// Setup outlink
|
||||||
GDMA.channel[0].out.out_link.addr = ((uint32_t)(&st->dmadesc_a[0]));// Set a vlaue here
|
GDMA.channel[0].out.out_link.addr = ((uint32_t)(&st->dmadesc_a[0]));// Set a value here
|
||||||
GDMA.channel[0].out.out_peri_sel.sel = SOC_GDMA_TRIG_PERIPH_I2S0; // 3 = I2S0
|
GDMA.channel[0].out.out_peri_sel.sel = SOC_GDMA_TRIG_PERIPH_I2S0; // 3 = I2S0
|
||||||
GDMA.channel[0].out.out_conf0.out_data_burst_en = 1;
|
GDMA.channel[0].out.out_conf0.out_data_burst_en = 1;
|
||||||
GDMA.channel[0].out.out_conf0.outdscr_burst_en = 1;
|
GDMA.channel[0].out.out_conf0.outdscr_burst_en = 1;
|
||||||
|
|
|
@ -99,7 +99,7 @@ void setup() {
|
||||||
|
|
||||||
// those are the defaults
|
// those are the defaults
|
||||||
mxconfig.mx_width = 64; // physical width of a single matrix panel module (in pixels, usually it is always 64 ;) )
|
mxconfig.mx_width = 64; // physical width of a single matrix panel module (in pixels, usually it is always 64 ;) )
|
||||||
mxconfig.mx_height = 32; // physical height of a single matrix panel module (in pixels, usually amost always it is either 32 or 64)
|
mxconfig.mx_height = 32; // physical height of a single matrix panel module (in pixels, usually almost always it is either 32 or 64)
|
||||||
mxconfig.chain_length = 1; // number of chained panels regardless of the topology, default 1 - a single matrix module
|
mxconfig.chain_length = 1; // number of chained panels regardless of the topology, default 1 - a single matrix module
|
||||||
mxconfig.gpio.r1 = R1; // pin mappings
|
mxconfig.gpio.r1 = R1; // pin mappings
|
||||||
mxconfig.gpio.g1 = G1;
|
mxconfig.gpio.g1 = G1;
|
||||||
|
|
|
@ -8,20 +8,20 @@ An excellent insight could be found here https://github.com/hzeller/rpi-rgb-led-
|
||||||
|
|
||||||
|
|
||||||
So there are two regs in this chip - **REG1** and **REG2**,
|
So there are two regs in this chip - **REG1** and **REG2**,
|
||||||
one could be written with 12 clock pusles (and usually called reg12, dunno why :))
|
one could be written with 12 clock pulses (and usually called reg12, dunno why :))
|
||||||
the other one could be written with 13 clock pulses (and usually called reg13, dunno why :))
|
the other one could be written with 13 clock pulses (and usually called reg13, dunno why :))
|
||||||
|
|
||||||
|
|
||||||
I've done some measurmens on power consumption while toggling bits of **REG1** and it looks that it could provide a fine grained brighness control over the entire matrix with no need for bitbanging over RGB or EO pins.
|
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.
|
||||||
There are 6 bits (6 to 11) giving an increased brighness (compared to all-zeroes) and 4 bits (2-5) giving decreased brighness!!!
|
There are 6 bits (6 to 11) giving an increased brightness (compared to all-zeroes) and 4 bits (2-5) giving decreased brightness!!!
|
||||||
Still unclear if FM6112A brightness control is internally PWMed or current limited, might require some poking with oscilloscope.
|
Still unclear if FM6112A brightness control is internally PWMed or current limited, might require some poking with oscilloscope.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
I'm not sure about bit 1 - it is either not used or I was unable to measure it's influence to brightness/power.
|
I'm not sure about bit 1 - it is either not used or I was unable to measure it's influence to brightness/power.
|
||||||
|
|
||||||
Giving at least 10 bits of hardware brightness control opens pretty nice options for offloading and simplifiyng matrix output. Should dig into this more deeper.
|
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.
|
||||||
|
|
||||||
Here are some of the measurments I've took for 2 64x64 panels filled with white color - reg value and corresponding current drain in amps.
|
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.
|
||||||
|
|
||||||
|
|
||||||
|REG1 |bit value|Current, amps |
|
|REG1 |bit value|Current, amps |
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
## FM6126 based LED Matrix Panel Reset ##
|
## FM6126 based LED Matrix Panel Reset ##
|
||||||
|
|
||||||
FM6216 panels require a special reset sequence before they can be used, check your panel chipset if you have issuees. Refer to this example.
|
FM6216 panels require a special reset sequence before they can be used, check your panel chipset if you have issues. Refer to this example.
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
float d = force.mag(); // Distance between objects
|
float d = force.mag(); // Distance between objects
|
||||||
d = constrain(d, 5.0, 32.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
|
d = constrain(d, 5.0, 32.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
|
||||||
force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
|
force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
|
||||||
float strength = (G * mass * m.mass) / (d * d); // Calculate gravitional force magnitude
|
float strength = (G * mass * m.mass) / (d * d); // Calculate gravitational force magnitude
|
||||||
force *= strength; // Get force vector --> magnitude * direction
|
force *= strength; // Get force vector --> magnitude * direction
|
||||||
return force;
|
return force;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,8 @@ Effects effects;
|
||||||
Patterns patterns;
|
Patterns patterns;
|
||||||
|
|
||||||
/* -------------------------- Some variables -------------------------- */
|
/* -------------------------- Some variables -------------------------- */
|
||||||
unsigned long fps = 0, fps_timer; // fps (this is NOT a matix refresh rate!)
|
unsigned long fps = 0, fps_timer; // fps (this is NOT a matrix refresh rate!)
|
||||||
unsigned int default_fps = 30, pattern_fps = 30; // default fps limit (this is not a matix refresh conuter!)
|
unsigned int default_fps = 30, pattern_fps = 30; // default fps limit (this is not a matrix refresh counter!)
|
||||||
unsigned long ms_animation_max_duration = 20000; // 20 seconds
|
unsigned long ms_animation_max_duration = 20000; // 20 seconds
|
||||||
unsigned long last_frame=0, ms_previous=0;
|
unsigned long last_frame=0, ms_previous=0;
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ uint16_t XY16( uint16_t x, uint16_t y);
|
||||||
/* Convert x,y co-ordinate to flat array index.
|
/* Convert x,y co-ordinate to flat array index.
|
||||||
* x and y positions start from 0, so must not be >= 'real' panel width or height
|
* x and y positions start from 0, so must not be >= 'real' panel width or height
|
||||||
* (i.e. 64 pixels or 32 pixels.). Max value: MATRIX_WIDTH-1 etc.
|
* (i.e. 64 pixels or 32 pixels.). Max value: MATRIX_WIDTH-1 etc.
|
||||||
* Ugh... uint8_t - really??? this weak method can't cope with 256+ pixel matrixes :(
|
* Ugh... uint8_t - really??? this weak method can't cope with 256+ pixel matrices :(
|
||||||
*/
|
*/
|
||||||
uint16_t XY( uint8_t x, uint8_t y)
|
uint16_t XY( uint8_t x, uint8_t y)
|
||||||
{
|
{
|
||||||
|
@ -56,7 +56,7 @@ uint16_t XY( uint8_t x, uint8_t y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The one for 256+ matrixes
|
* The one for 256+ matrices
|
||||||
* otherwise this:
|
* otherwise this:
|
||||||
* for (uint8_t i = 0; i < MATRIX_WIDTH; i++) {}
|
* for (uint8_t i = 0; i < MATRIX_WIDTH; i++) {}
|
||||||
* turns into an infinite loop
|
* turns into an infinite loop
|
||||||
|
@ -66,7 +66,7 @@ uint16_t XY16( uint16_t x, uint16_t y)
|
||||||
if( x >= MATRIX_WIDTH) return 0;
|
if( x >= MATRIX_WIDTH) return 0;
|
||||||
if( y >= MATRIX_HEIGHT) return 0;
|
if( y >= MATRIX_HEIGHT) return 0;
|
||||||
|
|
||||||
return (y * MATRIX_WIDTH) + x + 1; // everything offset by one to capute out of bounds stuff - never displayed by ShowFrame()
|
return (y * MATRIX_WIDTH) + x + 1; // everything offset by one to compute out of bounds stuff - never displayed by ShowFrame()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ public:
|
||||||
//CRGB leds2[NUM_LEDS]; // Faptastic: getting rid of this and any dependant effects or algos. to save memory 24*64*32 bytes of ram (50k).
|
//CRGB leds2[NUM_LEDS]; // Faptastic: getting rid of this and any dependant effects or algos. to save memory 24*64*32 bytes of ram (50k).
|
||||||
|
|
||||||
Effects(){
|
Effects(){
|
||||||
// we do dynamic allocation for leds buffer, otherwise esp32 toolchain can't link static arrays of such a big size for 256+ matrixes
|
// we do dynamic allocation for leds buffer, otherwise esp32 toolchain can't link static arrays of such a big size for 256+ matrices
|
||||||
leds = (CRGB *)malloc(NUM_LEDS * sizeof(CRGB));
|
leds = (CRGB *)malloc(NUM_LEDS * sizeof(CRGB));
|
||||||
|
|
||||||
// allocate mem for noise effect
|
// allocate mem for noise effect
|
||||||
|
@ -494,7 +494,7 @@ public:
|
||||||
leds[XY16(i, y - d)].nscale8(dimm);
|
leds[XY16(i, y - d)].nscale8(dimm);
|
||||||
}
|
}
|
||||||
for (int i = y - d; i <= y + d; i++) {
|
for (int i = y - d; i <= y + d; i++) {
|
||||||
leds[XY16(x + d, i)] += leds[XY16(x + d, i + 1)]; // right colum up
|
leds[XY16(x + d, i)] += leds[XY16(x + d, i + 1)]; // right column up
|
||||||
leds[XY16(x + d, i)].nscale8(dimm);
|
leds[XY16(x + d, i)].nscale8(dimm);
|
||||||
}
|
}
|
||||||
for (int i = x + d; i >= x - d; i--) {
|
for (int i = x + d; i >= x - d; i--) {
|
||||||
|
@ -502,7 +502,7 @@ public:
|
||||||
leds[XY16(i, y + d)].nscale8(dimm);
|
leds[XY16(i, y + d)].nscale8(dimm);
|
||||||
}
|
}
|
||||||
for (int i = y + d; i >= y - d; i--) {
|
for (int i = y + d; i >= y - d; i--) {
|
||||||
leds[XY16(x - d, i)] += leds[XY16(x - d, i - 1)]; // left colum down
|
leds[XY16(x - d, i)] += leds[XY16(x - d, i - 1)]; // left column down
|
||||||
leds[XY16(x - d, i)].nscale8(dimm);
|
leds[XY16(x - d, i)].nscale8(dimm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
class PatternSpiral : public Drawable {
|
class PatternSpiral : public Drawable {
|
||||||
private:
|
private:
|
||||||
// Timer stuff (Oszillators)
|
// Timer stuff (Oscillators)
|
||||||
struct timer {
|
struct timer {
|
||||||
unsigned long takt;
|
unsigned long takt;
|
||||||
unsigned long lastMillis;
|
unsigned long lastMillis;
|
||||||
|
@ -68,7 +68,7 @@ public:
|
||||||
// set all counting directions positive for the beginning
|
// set all counting directions positive for the beginning
|
||||||
for (int i = 0; i < timers; i++) multiTimer[i].delta = 1;
|
for (int i = 0; i < timers; i++) multiTimer[i].delta = 1;
|
||||||
|
|
||||||
// set range (up/down), speed (takt=ms between steps) and starting point of all oszillators
|
// set range (up/down), speed (takt=ms between steps) and starting point of all oscillators
|
||||||
|
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
@ -104,10 +104,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int drawFrame() {
|
unsigned int drawFrame() {
|
||||||
// manage the Oszillators
|
// manage the Oscillators
|
||||||
UpdateTimers();
|
UpdateTimers();
|
||||||
|
|
||||||
// draw just a line defined by 5 oszillators
|
// draw just a line defined by 5 oscillators
|
||||||
effects.BresenhamLine(
|
effects.BresenhamLine(
|
||||||
multiTimer[3].count, // x1
|
multiTimer[3].count, // x1
|
||||||
multiTimer[4].count, // y1
|
multiTimer[4].count, // y1
|
||||||
|
@ -116,7 +116,7 @@ public:
|
||||||
multiTimer[2].count); // color
|
multiTimer[2].count); // color
|
||||||
|
|
||||||
// manipulate the screen buffer
|
// manipulate the screen buffer
|
||||||
// with fixed parameters (could be oszillators too)
|
// with fixed parameters (could be oscillators too)
|
||||||
// Params: center x, y, radius, scale color down
|
// Params: center x, y, radius, scale color down
|
||||||
// --> NOTE: Affects always a SQUARE with an odd length
|
// --> NOTE: Affects always a SQUARE with an odd length
|
||||||
// effects.SpiralStream(15, 15, 10, 128);
|
// effects.SpiralStream(15, 15, 10, 128);
|
||||||
|
|
|
@ -63,9 +63,9 @@ class PatternSwirl : public Drawable {
|
||||||
// The color of each point shifts over time, each at a different speed.
|
// The color of each point shifts over time, each at a different speed.
|
||||||
uint16_t ms = millis();
|
uint16_t ms = millis();
|
||||||
effects.leds[XY(i, j)] += effects.ColorFromCurrentPalette(ms / 11);
|
effects.leds[XY(i, j)] += effects.ColorFromCurrentPalette(ms / 11);
|
||||||
//effects.leds[XY(j, i)] += effects.ColorFromCurrentPalette(ms / 13); // this doesn't work for non-square matrixes
|
//effects.leds[XY(j, i)] += effects.ColorFromCurrentPalette(ms / 13); // this doesn't work for non-square matrices
|
||||||
effects.leds[XY(ni, nj)] += effects.ColorFromCurrentPalette(ms / 17);
|
effects.leds[XY(ni, nj)] += effects.ColorFromCurrentPalette(ms / 17);
|
||||||
//effects.leds[XY(nj, ni)] += effects.ColorFromCurrentPalette(ms / 29); // this doesn't work for non-square matrixes
|
//effects.leds[XY(nj, ni)] += effects.ColorFromCurrentPalette(ms / 29); // this doesn't work for non-square matrices
|
||||||
effects.leds[XY(i, nj)] += effects.ColorFromCurrentPalette(ms / 37);
|
effects.leds[XY(i, nj)] += effects.ColorFromCurrentPalette(ms / 37);
|
||||||
effects.leds[XY(ni, j)] += effects.ColorFromCurrentPalette(ms / 41);
|
effects.leds[XY(ni, j)] += effects.ColorFromCurrentPalette(ms / 41);
|
||||||
|
|
||||||
|
|
|
@ -137,13 +137,13 @@ class Patterns : public Playlist {
|
||||||
// &incrementalDrift2, // 13 fail
|
// &incrementalDrift2, // 13 fail
|
||||||
&munch, // 14 ok
|
&munch, // 14 ok
|
||||||
&electricMandala, // 15 ok
|
&electricMandala, // 15 ok
|
||||||
// &spin, // 16 ok but repeditivev
|
// &spin, // 16 ok but repetitive
|
||||||
&simplexNoise, // 17 - cool!
|
&simplexNoise, // 17 - cool!
|
||||||
// &wave, // 18 ok (can't work with 256+ matrix due to uint8_t vars)
|
// &wave, // 18 ok (can't work with 256+ matrix due to uint8_t vars)
|
||||||
// &rainbowFlag, //20 // fail
|
// &rainbowFlag, //20 // fail
|
||||||
&attract, // 21 ok
|
&attract, // 21 ok
|
||||||
&swirl, // 22
|
&swirl, // 22
|
||||||
// &bounce, // boncing line crap
|
// &bounce, // bouncing line crap
|
||||||
&flock, // works
|
&flock, // works
|
||||||
&infinity, // works
|
&infinity, // works
|
||||||
&plasma, // works
|
&plasma, // works
|
||||||
|
|
|
@ -146,7 +146,7 @@ def bmp2hex(infile, tablewidth, sizebytes, invert, raw, named, double, xbm):
|
||||||
# Convert tablewidth to characters from hex bytes
|
# Convert tablewidth to characters from hex bytes
|
||||||
tablewidth = int(tablewidth) * 6
|
tablewidth = int(tablewidth) * 6
|
||||||
|
|
||||||
# Initilize output buffer
|
# Initialize output buffer
|
||||||
outstring = ''
|
outstring = ''
|
||||||
|
|
||||||
# Open File
|
# Open File
|
||||||
|
@ -165,7 +165,7 @@ def bmp2hex(infile, tablewidth, sizebytes, invert, raw, named, double, xbm):
|
||||||
if ((values[0] != 0x42) or (values[1] != 0x4D)):
|
if ((values[0] != 0x42) or (values[1] != 0x4D)):
|
||||||
sys.exit ("Error: Unsupported BMP format. Make sure your file is a Windows BMP.")
|
sys.exit ("Error: Unsupported BMP format. Make sure your file is a Windows BMP.")
|
||||||
|
|
||||||
# Calculate width, heigth
|
# Calculate width, height
|
||||||
dataOffset = getLONG(values, 10) # Offset to image data
|
dataOffset = getLONG(values, 10) # Offset to image data
|
||||||
pixelWidth = getLONG(values, 18) # Width of image
|
pixelWidth = getLONG(values, 18) # Width of image
|
||||||
pixelHeight = getLONG(values, 22) # Height of image
|
pixelHeight = getLONG(values, 22) # Height of image
|
||||||
|
|
|
@ -64,7 +64,7 @@ void loop()
|
||||||
|
|
||||||
for (int i = 0; i < numSquares; i++)
|
for (int i = 0; i < numSquares; i++)
|
||||||
{
|
{
|
||||||
// Draw rect and then calculatae
|
// Draw rect and then calculate
|
||||||
display->fillRect(Squares[i].xpos, Squares[i].ypos, Squares[i].square_size, Squares[i].square_size, Squares[i].colour);
|
display->fillRect(Squares[i].xpos, Squares[i].ypos, Squares[i].square_size, Squares[i].square_size, Squares[i].colour);
|
||||||
|
|
||||||
if (Squares[i].xpos >= display->width()) { Squares[i].velocityx *= -1; } else if (Squares[i].xpos <= 0) { Squares[i].velocityx = abs (Squares[i].velocityx); }
|
if (Squares[i].xpos >= display->width()) { Squares[i].velocityx *= -1; } else if (Squares[i].xpos <= 0) { Squares[i].velocityx = abs (Squares[i].velocityx); }
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
float d = force.mag(); // Distance between objects
|
float d = force.mag(); // Distance between objects
|
||||||
d = constrain(d, 5.0, 32.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
|
d = constrain(d, 5.0, 32.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
|
||||||
force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
|
force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
|
||||||
float strength = (G * mass * m.mass) / (d * d); // Calculate gravitional force magnitude
|
float strength = (G * mass * m.mass) / (d * d); // Calculate gravitational force magnitude
|
||||||
force *= strength; // Get force vector --> magnitude * direction
|
force *= strength; // Get force vector --> magnitude * direction
|
||||||
return force;
|
return force;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------- Display Config Initialisation -------------------- */
|
/* -------------------------- Display Config Initialisation -------------------- */
|
||||||
// Assume we have four 64x32 panels daizy-chained and ESP32 attached to the bottom right corner
|
// Assume we have four 64x32 panels daisy-chained and ESP32 attached to the bottom right corner
|
||||||
#define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
|
#define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
|
||||||
#define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
|
#define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
#define SERPENT false
|
#define SERPENT false
|
||||||
#define TOPDOWN false
|
#define TOPDOWN false
|
||||||
|
|
||||||
// Virtual Panl dimensions - our combined panel would be a square 4x4 modules with a combined resolution of 128x128 pixels
|
// Virtual Panel dimensions - our combined panel would be a square 4x4 modules with a combined resolution of 128x128 pixels
|
||||||
#define VPANEL_W PANEL_RES_X*NUM_COLS // Kosso: All Pattern files have had the MATRIX_WIDTH and MATRIX_HEIGHT replaced by these.
|
#define VPANEL_W PANEL_RES_X*NUM_COLS // Kosso: All Pattern files have had the MATRIX_WIDTH and MATRIX_HEIGHT replaced by these.
|
||||||
#define VPANEL_H PANEL_RES_Y*NUM_ROWS //
|
#define VPANEL_H PANEL_RES_Y*NUM_ROWS //
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ uint16_t XY16( uint16_t x, uint16_t y);
|
||||||
/* Convert x,y co-ordinate to flat array index.
|
/* Convert x,y co-ordinate to flat array index.
|
||||||
* x and y positions start from 0, so must not be >= 'real' panel width or height
|
* x and y positions start from 0, so must not be >= 'real' panel width or height
|
||||||
* (i.e. 64 pixels or 32 pixels.). Max value: VPANEL_W-1 etc.
|
* (i.e. 64 pixels or 32 pixels.). Max value: VPANEL_W-1 etc.
|
||||||
* Ugh... uint8_t - really??? this weak method can't cope with 256+ pixel matrixes :(
|
* Ugh... uint8_t - really??? this weak method can't cope with 256+ pixel matrices :(
|
||||||
*/
|
*/
|
||||||
uint16_t XY( uint8_t x, uint8_t y)
|
uint16_t XY( uint8_t x, uint8_t y)
|
||||||
{
|
{
|
||||||
|
@ -56,7 +56,7 @@ uint16_t XY( uint8_t x, uint8_t y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The one for 256+ matrixes
|
* The one for 256+ matrices
|
||||||
* otherwise this:
|
* otherwise this:
|
||||||
* for (uint8_t i = 0; i < VPANEL_W; i++) {}
|
* for (uint8_t i = 0; i < VPANEL_W; i++) {}
|
||||||
* turns into an infinite loop
|
* turns into an infinite loop
|
||||||
|
@ -66,7 +66,7 @@ uint16_t XY16( uint16_t x, uint16_t y)
|
||||||
if( x >= VPANEL_W) return 0;
|
if( x >= VPANEL_W) return 0;
|
||||||
if( y >= VPANEL_H) return 0;
|
if( y >= VPANEL_H) return 0;
|
||||||
|
|
||||||
return (y * VPANEL_W) + x + 1; // everything offset by one to capute out of bounds stuff - never displayed by ShowFrame()
|
return (y * VPANEL_W) + x + 1; // everything offset by one to compute out of bounds stuff - never displayed by ShowFrame()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ public:
|
||||||
CRGB *leds;
|
CRGB *leds;
|
||||||
|
|
||||||
Effects(){
|
Effects(){
|
||||||
// we do dynamic allocation for leds buffer, otherwise esp32 toolchain can't link static arrays of such a big size for 256+ matrixes
|
// we do dynamic allocation for leds buffer, otherwise esp32 toolchain can't link static arrays of such a big size for 256+ matrices
|
||||||
leds = (CRGB *)malloc(NUM_LEDS * sizeof(CRGB));
|
leds = (CRGB *)malloc(NUM_LEDS * sizeof(CRGB));
|
||||||
|
|
||||||
// allocate mem for noise effect
|
// allocate mem for noise effect
|
||||||
|
@ -491,7 +491,7 @@ public:
|
||||||
leds[XY16(i, y - d)].nscale8(dimm);
|
leds[XY16(i, y - d)].nscale8(dimm);
|
||||||
}
|
}
|
||||||
for (int i = y - d; i <= y + d; i++) {
|
for (int i = y - d; i <= y + d; i++) {
|
||||||
leds[XY16(x + d, i)] += leds[XY16(x + d, i + 1)]; // right colum up
|
leds[XY16(x + d, i)] += leds[XY16(x + d, i + 1)]; // right column up
|
||||||
leds[XY16(x + d, i)].nscale8(dimm);
|
leds[XY16(x + d, i)].nscale8(dimm);
|
||||||
}
|
}
|
||||||
for (int i = x + d; i >= x - d; i--) {
|
for (int i = x + d; i >= x - d; i--) {
|
||||||
|
@ -499,7 +499,7 @@ public:
|
||||||
leds[XY16(i, y + d)].nscale8(dimm);
|
leds[XY16(i, y + d)].nscale8(dimm);
|
||||||
}
|
}
|
||||||
for (int i = y + d; i >= y - d; i--) {
|
for (int i = y + d; i >= y - d; i--) {
|
||||||
leds[XY16(x - d, i)] += leds[XY16(x - d, i - 1)]; // left colum down
|
leds[XY16(x - d, i)] += leds[XY16(x - d, i - 1)]; // left column down
|
||||||
leds[XY16(x - d, i)].nscale8(dimm);
|
leds[XY16(x - d, i)].nscale8(dimm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
class PatternSpiral : public Drawable {
|
class PatternSpiral : public Drawable {
|
||||||
private:
|
private:
|
||||||
// Timer stuff (Oszillators)
|
// Timer stuff (Oscillators)
|
||||||
struct timer {
|
struct timer {
|
||||||
unsigned long takt;
|
unsigned long takt;
|
||||||
unsigned long lastMillis;
|
unsigned long lastMillis;
|
||||||
|
@ -68,7 +68,7 @@ public:
|
||||||
// set all counting directions positive for the beginning
|
// set all counting directions positive for the beginning
|
||||||
for (int i = 0; i < timers; i++) multiTimer[i].delta = 1;
|
for (int i = 0; i < timers; i++) multiTimer[i].delta = 1;
|
||||||
|
|
||||||
// set range (up/down), speed (takt=ms between steps) and starting point of all oszillators
|
// set range (up/down), speed (takt=ms between steps) and starting point of all oscillators
|
||||||
|
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
@ -104,10 +104,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int drawFrame() {
|
unsigned int drawFrame() {
|
||||||
// manage the Oszillators
|
// manage the Oscillators
|
||||||
UpdateTimers();
|
UpdateTimers();
|
||||||
|
|
||||||
// draw just a line defined by 5 oszillators
|
// draw just a line defined by 5 oscillators
|
||||||
effects.BresenhamLine(
|
effects.BresenhamLine(
|
||||||
multiTimer[3].count, // x1
|
multiTimer[3].count, // x1
|
||||||
multiTimer[4].count, // y1
|
multiTimer[4].count, // y1
|
||||||
|
@ -116,7 +116,7 @@ public:
|
||||||
multiTimer[2].count); // color
|
multiTimer[2].count); // color
|
||||||
|
|
||||||
// manipulate the screen buffer
|
// manipulate the screen buffer
|
||||||
// with fixed parameters (could be oszillators too)
|
// with fixed parameters (could be oscillators too)
|
||||||
// Params: center x, y, radius, scale color down
|
// Params: center x, y, radius, scale color down
|
||||||
// --> NOTE: Affects always a SQUARE with an odd length
|
// --> NOTE: Affects always a SQUARE with an odd length
|
||||||
// effects.SpiralStream(15, 15, 10, 128);
|
// effects.SpiralStream(15, 15, 10, 128);
|
||||||
|
|
|
@ -63,9 +63,9 @@ class PatternSwirl : public Drawable {
|
||||||
// The color of each point shifts over time, each at a different speed.
|
// The color of each point shifts over time, each at a different speed.
|
||||||
uint16_t ms = millis();
|
uint16_t ms = millis();
|
||||||
effects.leds[XY(i, j)] += effects.ColorFromCurrentPalette(ms / 11);
|
effects.leds[XY(i, j)] += effects.ColorFromCurrentPalette(ms / 11);
|
||||||
//effects.leds[XY(j, i)] += effects.ColorFromCurrentPalette(ms / 13); // this doesn't work for non-square matrixes
|
//effects.leds[XY(j, i)] += effects.ColorFromCurrentPalette(ms / 13); // this doesn't work for non-square matrices
|
||||||
effects.leds[XY(ni, nj)] += effects.ColorFromCurrentPalette(ms / 17);
|
effects.leds[XY(ni, nj)] += effects.ColorFromCurrentPalette(ms / 17);
|
||||||
//effects.leds[XY(nj, ni)] += effects.ColorFromCurrentPalette(ms / 29); // this doesn't work for non-square matrixes
|
//effects.leds[XY(nj, ni)] += effects.ColorFromCurrentPalette(ms / 29); // this doesn't work for non-square matrices
|
||||||
effects.leds[XY(i, nj)] += effects.ColorFromCurrentPalette(ms / 37);
|
effects.leds[XY(i, nj)] += effects.ColorFromCurrentPalette(ms / 37);
|
||||||
effects.leds[XY(ni, j)] += effects.ColorFromCurrentPalette(ms / 41);
|
effects.leds[XY(ni, j)] += effects.ColorFromCurrentPalette(ms / 41);
|
||||||
|
|
||||||
|
|
|
@ -135,13 +135,13 @@ class Patterns : public Playlist {
|
||||||
&incrementalDrift2, // 13 fail
|
&incrementalDrift2, // 13 fail
|
||||||
&munch, // 14 ok
|
&munch, // 14 ok
|
||||||
// &electricMandala, // 15 ok, but ugly (vortigont)
|
// &electricMandala, // 15 ok, but ugly (vortigont)
|
||||||
// &spin, // 16 ok but repeditivev
|
// &spin, // 16 ok but repetitive
|
||||||
// &simplexNoise, // 17 - cool!
|
// &simplexNoise, // 17 - cool!
|
||||||
// &wave, // 18 ok (can't work with 256+ matrix due to uint8_t vars)
|
// &wave, // 18 ok (can't work with 256+ matrix due to uint8_t vars)
|
||||||
// &rainbowFlag, //20 // fail
|
// &rainbowFlag, //20 // fail
|
||||||
&attract, // 21 ok
|
&attract, // 21 ok
|
||||||
// &swirl, // 22 ok, but ugly (vortigont)
|
// &swirl, // 22 ok, but ugly (vortigont)
|
||||||
// &bounce, // boncing line crap
|
// &bounce, // bouncing line crap
|
||||||
&flock, // works
|
&flock, // works
|
||||||
&infinity, // works
|
&infinity, // works
|
||||||
&plasma, // works
|
&plasma, // works
|
||||||
|
|
|
@ -103,7 +103,7 @@ class OneEighthMatrixPanel
|
||||||
*/
|
*/
|
||||||
inline VirtualCoords OneEighthMatrixPanel::getCoords(int16_t x, int16_t y) {
|
inline VirtualCoords OneEighthMatrixPanel::getCoords(int16_t x, int16_t y) {
|
||||||
|
|
||||||
coords.x = coords.y = -1; // By defalt use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer
|
coords.x = coords.y = -1; // By default use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer
|
||||||
|
|
||||||
// Check if virtual work co-ordinates are outside the virtual display resolution space. This does NOT check
|
// Check if virtual work co-ordinates are outside the virtual display resolution space. This does NOT check
|
||||||
// against the physical real-world DMA matrix resolution / setup configured, that is used to actually output
|
// against the physical real-world DMA matrix resolution / setup configured, that is used to actually output
|
||||||
|
@ -212,7 +212,7 @@ inline void OneEighthMatrixPanel::setRotate(bool rotate) {
|
||||||
if (rotate) { setRotation(1); } else { setRotation(0); }
|
if (rotate) { setRotation(1); } else { setRotation(0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to recreate this one, as it wouldnt work to just map where it starts.
|
// need to recreate this one, as it wouldn't work to just map where it starts.
|
||||||
inline void OneEighthMatrixPanel::drawIcon (int *ico, int16_t x, int16_t y, int16_t icon_cols, int16_t icon_rows) {
|
inline void OneEighthMatrixPanel::drawIcon (int *ico, int16_t x, int16_t y, int16_t icon_cols, int16_t icon_rows) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
#define OE_PIN 25
|
#define OE_PIN 25
|
||||||
#define CLK_PIN 22
|
#define CLK_PIN 22
|
||||||
|
|
||||||
#include "OneEighthScanMatrixPanel.h" // Virtual Display to re-map co-ordinates such that they draw correctly on a32x16 1/4 Scan panel
|
#include "OneEighthScanMatrixPanel.h" // Virtual Display to re-map co-ordinates such that they draw correctly on a 32x16 1/4 Scan panel
|
||||||
|
|
||||||
// placeholder for the matrix object
|
// placeholder for the matrix object
|
||||||
MatrixPanel_I2S_DMA *dma_display = nullptr;
|
MatrixPanel_I2S_DMA *dma_display = nullptr;
|
||||||
|
|
|
@ -74,7 +74,7 @@ class QuarterScanMatrixPanel : public Adafruit_GFX
|
||||||
return coords.y;
|
return coords.y;
|
||||||
}
|
}
|
||||||
// int16_t getVirtualY(int16_t y) {return getCoords(0,y).y;}
|
// int16_t getVirtualY(int16_t y) {return getCoords(0,y).y;}
|
||||||
/** extende function to draw lines/rects/... **/
|
/** extended function to draw lines/rects/... **/
|
||||||
virtual uint8_t width() {return VP_WIDTH;};
|
virtual uint8_t width() {return VP_WIDTH;};
|
||||||
virtual uint8_t height() {return VP_HEIGHT;};
|
virtual uint8_t height() {return VP_HEIGHT;};
|
||||||
|
|
||||||
|
@ -87,8 +87,8 @@ class QuarterScanMatrixPanel : public Adafruit_GFX
|
||||||
virtual void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y);
|
virtual void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y);
|
||||||
virtual void scrollChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint16_t dir, uint16_t speed);
|
virtual void scrollChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint16_t dir, uint16_t speed);
|
||||||
virtual void drawString(int16_t x, int16_t y, unsigned char* c, uint16_t color, uint16_t bg);
|
virtual void drawString(int16_t x, int16_t y, unsigned char* c, uint16_t color, uint16_t bg);
|
||||||
virtual size_t write(unsigned char c); // write a character on current cursor postion
|
virtual size_t write(unsigned char c); // write a character on current cursor position
|
||||||
virtual size_t write(const char *str); // write a character array (string) on curreont cursor postion
|
virtual size_t write(const char *str); // write a character array (string) on current cursor position
|
||||||
|
|
||||||
virtual void setTextWrap(bool w);
|
virtual void setTextWrap(bool w);
|
||||||
virtual void setCursor (int16_t x, int16_t y);
|
virtual void setCursor (int16_t x, int16_t y);
|
||||||
|
@ -127,7 +127,7 @@ class QuarterScanMatrixPanel : public Adafruit_GFX
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int16_t cursor_x, cursor_y; // Cursor position
|
int16_t cursor_x, cursor_y; // Cursor position
|
||||||
uint8_t size_x, size_y; // Font size Multiplikator default = 1 => 5x7 Font (5widht,7Height)
|
uint8_t size_x, size_y; // Font size Multiplier default = 1 => 5x7 Font (5width,7Height)
|
||||||
uint16_t textFGColor, textBGColor;
|
uint16_t textFGColor, textBGColor;
|
||||||
bool wrap ; // < If set, 'wrap' text at right edge of display
|
bool wrap ; // < If set, 'wrap' text at right edge of display
|
||||||
uint8_t dir ; // used for scrolling text direction
|
uint8_t dir ; // used for scrolling text direction
|
||||||
|
@ -150,7 +150,7 @@ class QuarterScanMatrixPanel : public Adafruit_GFX
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
void QuarterScanMatrixPanel::scrollText(const char *str,uint16_t speed, uint16_t pixels = 0) {
|
void QuarterScanMatrixPanel::scrollText(const char *str,uint16_t speed, uint16_t pixels = 0) {
|
||||||
// first we put all columns of every char inside str into a big array of lines
|
// first we put all columns of every char inside str into a big array of lines
|
||||||
// than we move through this arry and draw line per line and move this line
|
// than we move through this array and draw line per line and move this line
|
||||||
// one position to dir
|
// one position to dir
|
||||||
const uint8_t xSize = 6;
|
const uint8_t xSize = 6;
|
||||||
uint16_t len = strlen(str);
|
uint16_t len = strlen(str);
|
||||||
|
@ -308,7 +308,7 @@ inline void QuarterScanMatrixPanel::scrollChar(int16_t x, int16_t y, unsigned ch
|
||||||
fillRect(x,y,5,7,0);
|
fillRect(x,y,5,7,0);
|
||||||
x = lastX - s;
|
x = lastX - s;
|
||||||
for (int8_t i = 0; i < 5; i++) {
|
for (int8_t i = 0; i < 5; i++) {
|
||||||
// first line is the firste vertical part of a character and 8bits long
|
// first line is the first vertical part of a character and 8bits long
|
||||||
// last bit is everytime 0
|
// last bit is everytime 0
|
||||||
// we read 5 lines with 8 bit (5x7 char + 8bit with zeros)
|
// we read 5 lines with 8 bit (5x7 char + 8bit with zeros)
|
||||||
// Example : char A (90deg cw)
|
// Example : char A (90deg cw)
|
||||||
|
@ -320,7 +320,7 @@ inline void QuarterScanMatrixPanel::scrollChar(int16_t x, int16_t y, unsigned ch
|
||||||
uint8_t line = pgm_read_byte(&font[c * 5 + i]);
|
uint8_t line = pgm_read_byte(&font[c * 5 + i]);
|
||||||
// shift from right to left bit per bit
|
// shift from right to left bit per bit
|
||||||
// loop j = height of a character
|
// loop j = height of a character
|
||||||
// loop through a colunm of currenc character
|
// loop through a column of current character
|
||||||
Serial.printf("i:%d ", i);
|
Serial.printf("i:%d ", i);
|
||||||
// ignore all pixels outside panel
|
// ignore all pixels outside panel
|
||||||
if (x+i >= VP_WIDTH) continue;
|
if (x+i >= VP_WIDTH) continue;
|
||||||
|
@ -360,7 +360,7 @@ inline void QuarterScanMatrixPanel::drawChar(int16_t x, int16_t y, unsigned char
|
||||||
{
|
{
|
||||||
//Serial.printf("unmapped : drawChar(%d, %d, %c) \n",x, y, c);
|
//Serial.printf("unmapped : drawChar(%d, %d, %c) \n",x, y, c);
|
||||||
|
|
||||||
// note: remapping to 16x32 coordinats is done inside drawPixel() or fillRect
|
// note: remapping to 16x32 coordinates is done inside drawPixel() or fillRect
|
||||||
|
|
||||||
if ((x >= VP_WIDTH) ||
|
if ((x >= VP_WIDTH) ||
|
||||||
(y >= VP_HEIGHT) ||
|
(y >= VP_HEIGHT) ||
|
||||||
|
@ -377,14 +377,14 @@ inline void QuarterScanMatrixPanel::drawChar(int16_t x, int16_t y, unsigned char
|
||||||
//Serial.printf("");
|
//Serial.printf("");
|
||||||
drawPixel(x + i, y + j, color);
|
drawPixel(x + i, y + j, color);
|
||||||
else
|
else
|
||||||
// remark: it's important to call function with orgininal coordinates for x/y
|
// remark: it's important to call function with original coordinates for x/y
|
||||||
fillRect(x + i * size_x, y + j * size_y, size_x, size_y,
|
fillRect(x + i * size_x, y + j * size_y, size_x, size_y,
|
||||||
color);
|
color);
|
||||||
} else if (bg != color) {
|
} else if (bg != color) {
|
||||||
if (size_x == 1 && size_y == 1)
|
if (size_x == 1 && size_y == 1)
|
||||||
drawPixel(x + i, y + j, bg);
|
drawPixel(x + i, y + j, bg);
|
||||||
else
|
else
|
||||||
// remark: it's important to call function with orgininal coordinates for x/y
|
// remark: it's important to call function with original coordinates for x/y
|
||||||
fillRect(x + i * size_x, y + j * size_y, size_x, size_y, bg);
|
fillRect(x + i * size_x, y + j * size_y, size_x, size_y, bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,7 @@ inline void QuarterScanMatrixPanel::drawPixelRGB24(int16_t x, int16_t y, RGB24 c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// need to recreate this one, as it wouldnt work to just map where it starts.
|
// need to recreate this one, as it wouldn't work to just map where it starts.
|
||||||
inline void QuarterScanMatrixPanel::drawIcon (int *ico, int16_t x, int16_t y, int16_t module_cols, int16_t module_rows) { }
|
inline void QuarterScanMatrixPanel::drawIcon (int *ico, int16_t x, int16_t y, int16_t module_cols, int16_t module_rows) { }
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -44,7 +44,7 @@
|
||||||
#define LAT_PIN 4
|
#define LAT_PIN 4
|
||||||
#define E_PIN -1 // required for 1/32 scan panels
|
#define E_PIN -1 // required for 1/32 scan panels
|
||||||
|
|
||||||
#include "OneQuarterScanMatrixPanel.h" // Virtual Display to re-map co-ordinates such that they draw correctly on a32x16 1/4 Scan panel
|
#include "OneQuarterScanMatrixPanel.h" // Virtual Display to re-map co-ordinates such that they draw correctly on a 32x16 1/4 Scan panel
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -53,7 +53,7 @@ You have to use `setCursor(x,y)` and `setTextFGColor() / setTextBGColor()`
|
||||||
### drawString (5x7)
|
### drawString (5x7)
|
||||||
`void drawString(int16_t x, int16_t y, unsigned char* c, uint16_t color, uint16_t bg)`
|
`void drawString(int16_t x, int16_t y, unsigned char* c, uint16_t color, uint16_t bg)`
|
||||||
|
|
||||||
Draw String at postion x/y wit foreground `color` and background `bg`
|
Draw String at position x/y wit foreground `color` and background `bg`
|
||||||
Example: `display.drawString(0,5,"**Welcome**",display.color565(0,60,255));`
|
Example: `display.drawString(0,5,"**Welcome**",display.color565(0,60,255));`
|
||||||
|
|
||||||
### void setScrollDir(uint8_t d = 1)
|
### void setScrollDir(uint8_t d = 1)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Test Patterns
|
# Test Patterns
|
||||||
|
|
||||||
Simple solid colors, gradients and test line patterns, could be used to test matrixes for proper operation, flickering and estimate fillrate timings.
|
Simple solid colors, gradients and test line patterns, could be used to test matrices for proper operation, flickering and estimate fillrate timings.
|
||||||
|
|
||||||
Should be build and uploaded as a [platformio](https://platformio.org/) project
|
Should be build and uploaded as a [platformio](https://platformio.org/) project
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ void setup(){
|
||||||
matrix->begin();
|
matrix->begin();
|
||||||
matrix->setBrightness8(255);
|
matrix->setBrightness8(255);
|
||||||
|
|
||||||
// longer latch blanking could help to elliminate ghosting in some cases
|
// longer latch blanking could help to eliminate ghosting in some cases
|
||||||
//matrix->setLatBlanking(2);
|
//matrix->setLatBlanking(2);
|
||||||
|
|
||||||
ledbuff = (CRGB *)malloc(NUM_LEDS * sizeof(CRGB)); // allocate buffer for some tests
|
ledbuff = (CRGB *)malloc(NUM_LEDS * sizeof(CRGB)); // allocate buffer for some tests
|
||||||
|
@ -383,7 +383,7 @@ void IRAM_ATTR mxfill(CRGB *leds){
|
||||||
//
|
//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The one for 256+ matrixes
|
* The one for 256+ matrices
|
||||||
* otherwise this:
|
* otherwise this:
|
||||||
* for (uint8_t i = 0; i < MATRIX_WIDTH; i++) {}
|
* for (uint8_t i = 0; i < MATRIX_WIDTH; i++) {}
|
||||||
* turns into an infinite loop
|
* turns into an infinite loop
|
||||||
|
|
Loading…
Reference in a new issue