Request: support for 128 pixel height (kMatrixHeight)

Hi Louis,

I’ve been following the 64x64 HUB75E thread pretty closely, and I’d love it if you could support kMatrixHeight = 64 in the future. My hope is to have 4 64x64 panels in a square pushed by a Teensy 3.5.

I know you mentioned a v5 shield in the works. I love this product and just wanted to get that wish out there.

Cheers,
-Vince

Hi Vince, I think there’s support for what you need right now. It’s not packaged up into a release, but if you can download the library from GitHub and add it to your Arduino libraries folder, should be good to go.

This commit after the last release added support for 64x64/32 panels.

Download the latest commits from here:

To support 128 x 128 with 4x 64x64, just set kMatrixHeight = 128, kMatrixWidth = 128, and the library automatically wraps the last two panels to create the bottom row. Order the chain like this:

1   2
3   4
1 Like

I’m not working on a V5 shield for Teensy, I don’t expect any Teensy hardware improvements for the near future. I am working on a shield for the ESP32, as I’ve wanted to add WiFi support to SmartMatrix for a long time now, and the ESP32 is capable.

If you get it working, please post back, I’d love to see what 128x128 pixels looks like!

Hi Louis,

I’ve been fighting it all day, but no luck so far. I pulled the newest commit and updated the two new files, but I may be missing something else.

Here’s my code:

#include <SmartLEDShieldV4.h>  // uncomment this line for SmartLED Shield V4 (needs to be before #include <SmartMatrix3.h>)
#include <SmartMatrix3.h>
#include "colorwheel.c"
#include "gimpbitmap.h"

#define COLOR_DEPTH 24                  // known working: 24, 48 - If the sketch uses type `rgb24` directly, COLOR_DEPTH must be 24
const uint8_t kMatrixWidth = 64;        // known working: 32, 64, 96, 128
const uint8_t kMatrixHeight = 64;       // known working: 16, 32, 48, 64
const uint8_t kRefreshDepth = 36;       // known working: 24, 36, 48
const uint8_t kDmaBufferRows = 4;       // known working: 2-4, use 2 to save memory, more to keep from dropping frames and automatically lowering refresh rate
const uint8_t kPanelType = SMARTMATRIX_HUB75_64ROW_MOD32SCAN;
//const uint8_t kPanelType = SMARTMATRIX_HUB75_32ROW_MOD16SCAN;   // use SMARTMATRIX_HUB75_16ROW_MOD8SCAN for common 16x32 panels
const uint8_t kMatrixOptions = (SMARTMATRIX_OPTIONS_NONE);      // see http://docs.pixelmatix.com/SmartMatrix for options
const uint8_t kBackgroundLayerOptions = (SM_BACKGROUND_OPTIONS_NONE);
const uint8_t kScrollingLayerOptions = (SM_SCROLLING_OPTIONS_NONE);
const uint8_t kIndexedLayerOptions = (SM_INDEXED_OPTIONS_NONE);

64x64 works fine, but anything else just blanks out the panels.

Am I missing something?

-Vince

Are you using a Teensy 3.5 or 3.6? A 3.2 won’t have enough memory

Hi Louis,

I’m using a 3.5. I ordered the panels from the supplier you referenced in the 64x64 thread.

Here are a couple of photos with just 2 panels:

kMatrixWidth = 64 / kMatrixHeight = 64

kMatrixWidth = 128 / kMatrixHeight = 64

The code compiles, which lets me know I got the GitHub files correctly. Were there any other files updated? The 64x64 thread (Modify code for 64*64 pixel, HUB75E, 1/32 Scan led panels) mentions a third file (MatrixHardware_KitV1.h)

-Vince

Hi Vince,

I can’t find my 3.5, but I just tried with a 3.6. I get similar results as you. 64x128 and 128x64 both worked but not 128x128. I tried lowering kRefreshDepth to 24, which does make FeatureDemo work at 128x128, but just barely. I’m not sure exactly where the bottleneck is, but the Teensy 3.6 is having a hard time refreshing 128x128 pixels at once. The refresh rate is automatically lowered when the Teensy can’t keep up, and in my case, it got automatically lowered to 47FPS (default is 128FPS), and I see significant flicker. The 3.5 will probably fare worse than the 3.6.

I tried a simpler sketch - Bitmaps - and it refreshes at 96FPS with 24-bit color. I know the scrolling text layer isn’t as efficient as it could be, and the Bitmaps sketch doesn’t have that layer. The indexed layer might also be a bit inefficient as well.

There’s another hack you can do to squeeze a bit more out of the SmartMatrix Library:

comment out this line in SmartMatrix_Impl.h:

    // also enable for now, until it can be selectively enabled for higher clock speeds (140MHz+) where the data rate is too high for the panel
    //dmaClockOutData.TCD->CSR |= (0x02 << 14);

replace this line in MatrixHardware_KitV4 (halving the time waited for data to shift out):

#define PANEL_32_PIXELDATA_TRANSFER_MAXIMUM_NS  (uint32_t)((3400 * 96000000.0) / F_CPU)

This hack may not work in all cases, e.g. if you’re using a SD card for AnimatedGIFs, there’s likely to be DMA conflicts that will show up as artifacts on the LED screen. With the Bitmaps sketch, I get 104FPS after making that change (using the 3.6).

Sorry this isn’t working. You’re on the cutting edge of SmartMatrix projects, I haven’t even tried these configurations myself. If you can share a bit about what you’re trying to do with your project, I can try to point you in the right direction. For this amount of pixels you might be better off driving from a Raspberry Pi with this shield, though I don’t know if 128x128 is supported.

Louis

Hi Louis,

I’m working on an art project that uses a Teensy 3.5 to pull images off my API using a WINC1500. The images get stored on the Teensy’s SD card, then displayed via the SmartMatrix. This setup worked very nicely with a Teensy 3.2 and 4 32x32 matrices. Here’s the production diary: https://goo.gl/photos/tDPa53GPiDFtMbK2A - V1
https://goo.gl/photos/n7BMBbdWyUhu7cnv8 - prototype using Neopixels

I’ve been following the Adafruit shield, but I think a linux box is overkill for simple API calls (I once used an Arduino Yun for the same project). Also, I’m encouraged that you got 128x128 to work. My code is a ton simpler than FeatureDemo, despite the WiFi handling. In fact, it runs nicely on a single 64x64.

When I get home, I’ll try the following, in this order:

  1. kRefreshDepth to 24
  2. disable ScrollingLayer (I may be able to live w/o it and just draw my texts)
  3. try disabling Indexed layer

I’ll let you know what I find.

Cheers,

-Vince

Hi Louis,

No luck on the tests. You were right about the Teensy 3.5 vs 3.6. I could get neither (a severely stripped-down) FeatureDemo nor Bitmaps to work.

I’m not giving up, though. I’m going to try a 3.6 with this, though I’m expecting 3.3v hassles with the WiFi breakout.

I’ll have an update when the boards arrive.

Cheers,

-Vince

Are you using the Adafruit WINC1500 breakout? At a glance it looks like that breakout is only boosting 3.3V inputs to 5V, and the outputs (e.g. MISO) are left at the WINC1500’s 3.3V level.

I agree with you that a linux board is overkill. Hopefully you can get it to work with the Teensy 3.6.

Louis

Yup. It’s the Adafruit breakout. I’ve had good luck teaming them w/ Teensy 3.2 and your v3 shields, also w/ 3.5 and your v4. Those are both 5v-tolerant as you know. I’ll go slow w/ the 3.6 as I’ve killed one in the past before I found that it was not. :slight_smile:

-Vince

Hi Louis,

I’m happy to report that my project works with 128x128 on Teensy 3.6! Thanks for the suggestions!

Even with the increased array sizing to handle transitions between each pixel, It compiles with room to spare:

Sketch uses 105452 bytes (10%) of program storage space. Maximum is 1048576 bytes.
Global variables use 198900 bytes (75%) of dynamic memory, leaving 63244 bytes for local variables. Maximum is 262144 bytes.

Sample photos (ignore the blue tape holding the panels together):
Google Photos
Google Photos

It was refreshing at 47FPS, with visible flicker. I’m managing 59FPS (less noticable flicker) by setting the optimize option to “fastest”. I ran it in overclock(240MHz) and got up to 67FPS. I’m working on a few tweaks to see if I can increase the FPS w/o overclocking. Any suggestions would be appreciated.

Here’s my init code:

//SmartMatrix:
#include <SmartLEDShieldV4.h>
#include <SmartMatrix3.h>
#define COLOR_DEPTH 24 // known working: 24, 48 - If the sketch uses type rgb24 directly, COLOR_DEPTH must be 24
const uint8_t kMatrixWidth = 128; // known working: 32, 64, 96, 128
const uint8_t kMatrixHeight = 128; // known working: 16, 32, 48, 64
const uint8_t kRefreshDepth = 24; // known working: 24, 36, 48 (higher number will result in visible flicker)
const uint8_t kDmaBufferRows = 4; // known working: 2-4, use 2 to save memory, more to keep from dropping frames and automatically lowering refresh rate
const uint8_t kPanelType = SMARTMATRIX_HUB75_64ROW_MOD32SCAN;
const uint8_t kMatrixOptions = (SMARTMATRIX_OPTIONS_NONE); // see SmartMatrix - Overview for options
const uint8_t kBackgroundLayerOptions = (SM_BACKGROUND_OPTIONS_NONE);
const uint8_t kScrollingLayerOptions = (SM_SCROLLING_OPTIONS_NONE);
const uint8_t kIndexedLayerOptions = (SM_INDEXED_OPTIONS_NONE);

Cheers,

-Vince

Hi Vince,

I’m glad you got it working, though I wish the framerate was higher. You could try to increase kDmaBufferRows, though I don’t know if it will help. Is your sketch using just the background layer, or also scrolling and indexed layers? Fewer layers will refresh faster.

It doesn’t help you right now, but the ESP32 port I’m working on may be able to better refresh large panels like this. The ESP32 has enough RAM to hold complete frames in memory instead of needing to build up the refresh data row by row on the fly. That allows you to keep the panel refresh rate high without increasing CPU load.

Hi Louis,

I commented out indexedLayer and got it up to 75FPS. I confess to not knowing what that layer did and apparently never tried removing it. I did get a compilation warning but everything works! Looks great.

Thanks for your help on this!

I look forward to your ESP port, but be warned I will find its limits :wink:

-Vince

IndexedLayer can be used for a single color bitmap or text displayed above the background. A typical use is to put a digital clock above something like an Animated GIF.

I’m posting work-in-progress updates on the ESP32 port here. I’m not too far away from releasing the first SmartMatrix Library ESP32 port, so subscribe to that thread if you want the latest: I2S-parallel example: Drive a 64x32 display - Page 4 - ESP32 Forum

I like the patterns you’re displaying in your test photos, are those Animated GIFs? Your creations or something you found?

Louis

1 Like

Glad to hear I can do without that layer. I now consider this build rock solid. Onward!

The patterns in the photos are somewhat random, based on some raw source images I created for my API. The SmartMatrix/Teensy fetches a new image about every minute. The API can create trillions of combinations, so you never see the same pattern twice. I’m working on a few sets of raw source images and the ability to control everything with a webapp.

The 128x128 matrices were a game changer, and they’ve sent me back to the drawing board in a sense. It’s all worth it though, to double the resolution. I’m thrilled with these updates!

1 Like

Hi Vince,

I’m still working on the ESP32 port, and though I thought 128x128 support would be easy, it’s pushing the normal ESP32 boards beyond their limits. There’s 512kB SRAM in a typical ESP32 module - double the amount in the Teensy 3.6 - but within that there’s 96k of memory that’s only accessible via 32-bit addresses and doesn’t support DMA, which rules out using it for SmartMatrix Library or many other libraries. Because the ESP32 DMA architecture requires keeping two full refresh frames in memory, vs the Teensy requiring only two rows in memory, the memory in the ESP32 gets used up quick. I have some ideas on how to use the remaining 96kB for the background layer, so a 128x128 display can be supported, but it’s a difficult project and I’m unlikely to get to it anytime soon, if at all. A board using the ESP32 WROVER module might work as it adds a larger external memory, but I haven’t tried it yet as I haven’t found anyone selling the module in the same “Dev Kit C” form factor my shield uses.

Just wanted to give you a heads up that the Teensy 3.6 is still likely the best micro for your project.

Hi @Louis @vincefarq
Given that I had enough panels laying around (32x64), I made a 128x128 matrix with them, and I can’t get my teensy 3.6 to drive more than 96x128. If I do 128x128, it just crashes.
I tried the original teensy master branch, TOT (not teensylc)

I went super basic, like below:

#define COLOR_DEPTH 24                  // known working: 24, 48 - If the sketch uses type `rgb24` directly, COLOR_DEPTH must be 24
const uint8_t kMatrixWidth = 128;        // known working: 32, 64, 96, 128
const uint8_t kMatrixHeight = 128;       // known working: 16, 32, 48, 64
const uint8_t kRefreshDepth = 24;       // known working: 24, 36, 48
const uint8_t kDmaBufferRows = 2;       // known working: 2-4, use 2 to save memory, more to keep from dropping frames and automatically lowering refresh rate
const uint8_t kPanelType = SMARTMATRIX_HUB75_32ROW_MOD16SCAN;   // use SMARTMATRIX_HUB75_16ROW_MOD8SCAN for common 16x32 panels
//const uint8_t kPanelType = SMARTMATRIX_HUB75_64ROW_MOD32SCAN;
const uint8_t kMatrixOptions = (SMARTMATRIX_OPTIONS_NONE);      // see http://docs.pixelmatix.com/SmartMatrix for options
const uint8_t kBackgroundLayerOptions = (SM_BACKGROUND_OPTIONS_NONE);

SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth, kMatrixHeight, kRefreshDepth, kDmaBufferRows, kPanelType, kMatrixOptions);
SMARTMATRIX_ALLOCATE_BACKGROUND_LAYER(backgroundLayer, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kBackgroundLayerOptions);

I don’t really need 128x128, but it would have been nice to see it work.

Sketch uses 27440 bytes (2%) of program storage space. Maximum is 1048576 bytes.
Global variables use 123892 bytes (47%) of dynamic memory, leaving 138252 bytes for local variables. Maximum is 262144 bytes.

I took drawBitmap from featuredemo and don’t run anything else, I kept it very simple

Given that’s it’s not an ESP32, I get no output on teensy, so it’s hard to know why it’s not happy. Well, printf debugging shows it seems to die here:

    	Serial.println("before");
        backgroundLayer.fillScreen(defaultBackgroundColor);
        backgroundLayer.swapBuffers();
    	Serial.println("after");

Going back to 96x128 and it works fine.
Any ideas?

Hi @marcmerlin,

That code looks fine to me. Did you include the SmartLEDShieldV4.h library? I’m assuming you’d see a ton of compile errors if you didn’t, but it’s worth asking.

Here’s my current code in case it helps. This seems to work for me on the 4 64x64 matrices I mentioned in this thread.

//SmartMatrix:
#include <SmartLEDShieldV4.h>
#include <SmartMatrix3.h>
#define COLOR_DEPTH 24 // known working: 24, 48 - If the sketch uses type `rgb24` directly, COLOR_DEPTH must be 24
const uint8_t kMatrixWidth = 128; // known working: 32, 64, 96, 128
const uint8_t kMatrixHeight = 128; // known working: 16, 32, 48, 64
const uint8_t kRefreshDepth = 24; // known working: 24, 36, 48 (higher number will result in visible flicker)
const uint8_t kDmaBufferRows = 4; // known working: 2-4, use 2 to save memory, more to keep from dropping frames and automatically lowering refresh rate
const uint8_t kPanelType = SMARTMATRIX_HUB75_64ROW_MOD32SCAN;
const uint8_t kMatrixOptions = (SMARTMATRIX_OPTIONS_NONE);
const uint8_t kBackgroundLayerOptions = (SM_BACKGROUND_OPTIONS_NONE);
const uint8_t kScrollingLayerOptions = (SM_SCROLLING_OPTIONS_NONE);
SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth, kMatrixHeight, kRefreshDepth, kDmaBufferRows, kPanelType, kMatrixOptions);
SMARTMATRIX_ALLOCATE_BACKGROUND_LAYER(backgroundLayer, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kBackgroundLayerOptions);
SMARTMATRIX_ALLOCATE_SCROLLING_LAYER(scrollingLayer, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kScrollingLayerOptions);
const int defaultScrollOffset = 1;
const rgb24 defaultBackgroundColor = {0, 0, 0};

void setup() {

  //SmartMatrix:
  matrix.addLayer(&backgroundLayer); 
  matrix.addLayer(&scrollingLayer); 
  matrix.begin();
  matrix.setBrightness(defaultBrightness);
  scrollingLayer.setOffsetFromTop(defaultScrollOffset);
  backgroundLayer.enableColorCorrection(true);

  scrollingLayer.setMode(wrapForward);
  scrollingLayer.setSpeed(30);
  scrollingLayer.setFont(font6x10);

  backgroundLayer.fillScreen(defaultBackgroundColor); backgroundLayer.swapBuffers(); // clear screen

  Serial.begin(9600);

  Serial.println("Hello there"); 

  scrollingLayer.start("Hello" , 1);

}