Closed embedded-creations closed 8 years ago
update: some test-patterns seem to hang (currently investigating with refreshrates <= 70)
(eg: DEMO_DRAWING_FILLED, DEMO_SCROLL_MODES)
the image is not distorted or so (which is the case when teensy crashes) but stays frozen (-> the PMW-generation keeps going) timer problem?
@mrwastl Memory usage should be more, or at least more visible when you compile, as the 2.3kB tempRow buffers (for matrixWidth=6x32) are now static instead of on the stack.
A stuck image usually means the application is stuck somewhere. Either the code inside loop() is broken for a large matrixWidth, or a method inside SmartMatrix can't handle it. I'll get those fixed at some point, but I'm focusing on lower level details now. You can just disable those sections of FeatureDemo.
I just pushed code that is able to detect when matrixCalculations() hasn't been able to keep up, and puts DMA into an idle state with the screen blank until matrixCalculations() has more data and starts everything back up. I have it set to automatically lower the refresh rate by 1Hz every time this happens, otherwise matrixCalculations() will never return and let loop() run, so all you see is a black screen (though it is refreshing). I'll probably add some methods so the user can see if the refresh rate was lowered, and get the new refresh rate. I tested this with FastLED_Functions set to width 6x32, which automatically lowers the refresh rate to ~40Hz to keep up (loop runs at 6FPS). It flickers a lot and the FPS is horribly slow, but it's much better than a blank screen or crashed sketch.
@mrwastl You'll be pleased to know I started thinking about adding support for tiling panels.
Up until now, there's just been one description for screen size which applies to the Layers containing graphics and the SmartMatrix class which refreshes the panels. I think there needs to be a description of the Layer's size, a separate description of the refresh layout, and a mapping between the two.
Example describing a 96x64 display built with 32x32 panels: backgroundLayer is width 96, height 64 SmartMatrix refresh layout is width 192, height 32 mapping: Z-chaining, Divide chain by 2
Having two different widths and heights might be confusing for some people, and may make the initialization at the beginning of the sketch complex. Describing the refresh layout as simply width and height hides the fact that you can't specify arbitrary width and height, it's dependent on the panels. I think describing the refresh layout in terms of panels might be better.
Example describing a 96x64 display built with 32x32 panels: backgroundLayer is width 96, height 64 SmartMatrix refresh layout is using 32x32 HUB75 panels, 6 panels in chain, stacked 2 high mapping: Z-chaining
I think this better separates and describes how you assemble the display hardware and how you draw to the display. I'll continue on this next week, please let me know what you think
OK, it took a few hours, but I finally have Aurora compiling and running with the latest SM3 changes. Some of that was updating to the latest Arduino and Teensyduino releases, re-applying offset and MSD changes to platforms and boards files, etc.
I still need to spend some time separating what used to be two layers (background and foreground) to three (background, scrolling, and indexed). I plan to move all clock, status change indicators (brightness, playmode, etc) to the indexed layer, leaving only scrolling text (menus) on the scrolling layer.
@embedded-creations why so complicated?
as far as i know there're only 2 different types of panels: 32x16 and 32x32 (even the 64x32 are technically just 2 * 32x32 if i've read correctly).
so you can get all information that is needed out of kMatrixHeight, kMatrixWidth and an optional kPanelHeight (which defaults to 32). and an optional chaining (with a default option (Z or C)).
the internal mapping is more or less trivial - except for one category of methods: geom. figures (drawHardware*) and for kPanelHeight = 16 (support for rotation - this led to some problems as far as i remember).
or do you think about supporting more than just 'rectangular' displays (cube displays, different panels that display different content, but are controlled by one source, ...). well yes. than it would be a little bit more complicated ...
some notes to the current commits: i currently can just use 5 panels (when using 6 panels, no matter if
i use kRefreshDepth = 36
or kRefreshDepth = 24
, the display generation crashes (when using kMatrixWidh = 5 * 32
and kRefreshDepth = 24
there's still ~ 20k dyn. mem left according to the arduino IDE (sketch = FeatureDemo)). when using kRefreshDepth = 36
i can only use 4 panels.
the problem with the frozen image might be an interesting too:
if i switch to git version 8efdd479706cfd7bbd5183f3e250047d05893c5a (~ april 21) i get a frozen image too, but only with DEMO_DRAWING_FILLED
. the pattern generation ends before the end of the scrolling text (background pattern stops, scrolling text still scrolling, scrolling text ends -> image is frozen forever). if i set transitionTime = 4000
instead of transitionTime = 8500
than switching to the next demo is done before the end of the pattern generation and no freeze occurs (well, text scrolling is interupted though ...).
(other parameters: kMatrixWidth = 8 * 32
, kRefreshDepth = 36
, refreshrate = 95)
i didn't do these tests with reduced transitionTime with later version but i guess the cause might be similar. maybe this helps you with debugging the frozen image problem.
@mrwastl You're right, I'm probably overcomplicating it. I did consider the mapping for a cube, but I think that's a special case that should probably be treated as a 32x192 chain of panels for the refresh layout, and a custom layer can map to the six faces. I'm considering supporting other types of panels in the future, so specifying panel height is not enough.
backgroundLayer is width 96, height 64 panel type: 32-pixel high HUB75 1/16 scan (HUB75 describes clocking out two rows simultaneously, 1/16 scan describes how many rows are lit up at a time) tiling pattern: Z SmartMatrix refresh layout can be determined by the overall width and height, panel type, and tiling pattern
I guess I need to decide how to pass the panel type and tiling pattern. Tiling pattern seems like an option handled by the existing optionFlags. Panel Type could be selected by a series of bits in options, or a separate template argument.
matrixWidth is going to need to be a template argument now, as the size of the tempRow buffers can't be determined without width, height, and panel type.
OK, I pushed initial support for vertically stacking panels. Will implement Z-style chaining and do more testing tomorrow. I just tested with two 32x32 panels stacked on top of each other. FastLED_Functions doesn't look right, as it isn't designed for >32 pixels high, but it does work.
A definition is needed before it looks like it should be ready: the size of matrixUpdateData
depends on MATRIX_PANEL_HEIGHT
, which is not defined until panel_type
is passed as a template argument to SmartMatrix3 two lines later. Somehow it works though. I guess templates are set up by the compiler before the preprocessor runs.
Options for panelType
are as of now:
SMARTMATRIX_HUB75_32ROW_MOD16SCAN
SMARTMATRIX_HUB75_16ROW_MOD8SCAN
All that information is needed, at least for future proofing: HUB75 says two rows are updated per clock (vs HUB08 - one example: Thin 16x32 RGB Matrix) Number of rows and scan type is needed, as a 32-Row 1/8-scan display will tile differently than a 16-row 1/8-scan display. I initially thought either panel height or scan type would be enough, but there could be confusion in the future.
hi, i've already been testing your changes before reading your latest message (the comments in your source code are very self-explaining :)
you seem to have implemented Z-style chaining, but upper and lower half swapped (the upper panel row shows the lower part of the image - no rotation or so, just swapped - i'm already testing with 96x64).
i had to deactivate all indexed layer stuff to be able to test with 6 panels (indexedLayer, DEMO_COLOR_CORRECTION, DEMO_INDEXED_LAYER, DEMO_READ_PIXEL, DEMO_REFRESH_RATE) but now it seems to work fine - with the following exception: kRefreshDepth = 36
is working, kRefreshDepth = 24
crashes. i absolutely don't understand why (teensy craziness, ...).
well, and the timing problem (frozen image) seems to still be there (seems that while(scrollingLayer.getStatus());
in DEMO_SCROLL_MODES
causes problems).
Edit: i haven't tested further than DEMO_SCROLL_MODES
yet.
i've replaced (MATRIX_STACK_HEIGHT-i-1) * MATRIX_PANEL_HEIGHT
through i * MATRIX_PANEL_HEIGHT
(6 times) and now my panel (Z-chaining) shows a perfect image.
i might have found the problem that causes the frozen image problem: while(scrollingLayer.getStatus());
and an overclocked teensy don't seem to go together very well. i've added a simple delay(1);
in getStatus()
right before return scrollcounter;
: no more freezing (DEMO_SCROLL_MODES, DEMO_SCROLL_FONTS and DEMO_SCROLL_ROTATION now work as expected).
@mrwastl Apparently I don't know the difference between the shape of a 'C' and a 'Z' :-) I'll add support for C chaining, and I guess support for changing the direction of the stacking. Does your setup look like this, where "1" is connected to the SmartMatrix Shield?
| 4 | 5 | 6 | | 1 | 2 | 3 |
I was stacking the opposite way.
Thanks for narrowing down the frozen image problem. Its actually not related to overclocking or screen size, it fails for me at 48MHz with a 32x32 screen. I'll track it down.
here i've described the different wiring schemes (the Z-chaining is based on GaryBoone's modifications) starting at line 92:
https://github.com/mrwastl/SmartMatrix/blob/master/MatrixHardware_KitV1_generic.h
frozen image:
i guess the while(doSomething()) ;
doesn't give the teensy or the code enough time to 'breath'.
just adding a simple nop() or delay(); (while (doSomething()) { delay(1); }
) solved this (as i didn't want to change each while()-loop i changed the method).
for your information:
the rotation was already working fine with all 4 rotation-tests (90, 180, 270, 0 degrees). - in my fork i only got 0 degrees working without problems ...
@mrwastl scrollcounter is updated in an ISR and needed to be set volatile - fixed. When calling getScrollStatus()
through the SmartMatrix passthrough function, the compiler would check the variable every time, but without that layer of indirection, it optimized out repeated checking.
@mrwastl
in my fork i only got 0 degrees working without problems ...
There were a lot of (my) bugs in the foreground drawing code, swapping matrixWidth/matrixHeight, which didn't matter at 32x32, but does for non-square displays. It took a while to get those fixed and rotation working.
@mrwastl
it seems to work fine - with the following exception: kRefreshDepth = 36 is working, kRefreshDepth = 24 crashes
I can reproduce this with a 96MHz clock. Lowering kDmaBufferRows to 2 (the absolute minimum) lets it run a little longer but it still crashes. It works fine for a 64x64 screen.
Side effects of lowering kDmaBufferRows: matrixCalculations() will never loop, calculating data for more than one row during the ISR. Decreased memory usage.
@mrwastl I pushed an improvement, let me know if it gets rid of the occasional single row glitch called it on your setup. I haven't noticed any since I made the change, though I can't explain why this fixed it.
C-style chaining is supported now, that was a pain. It even works for more than a stack of two, so you could make a tall 32x128 display if you wanted, though rotation makes more sense. I made support for >2 stacks to cover this use case, a 96x48 display made up of 16x32 panels stacked 3x high.
The timers are now set up to closely match refreshRate, and not be slower. The default refreshRate is now 120, instead of 135 which used to result in refreshing at ~120 FPS.
Behind the scenes details: there's a minimum time needed to handle DMA for a given color depth bit before moving to the next one. Small bits need much less time than the minimum, so I add padding to the timers where the screen is off, just waiting for the minimum time. These add up, and the easy way to calculate was to use ideal numbers and just ignore the fact that the screen was refreshing slower than requested. Now the minimum times are taken into account, and the ideal time per bit is decreased until all the timer values are less than 1/refreshRate.
A definition is needed before it looks like it should be ready Somehow it works though. I guess templates are set up by the compiler before the preprocessor runs.
Nope, doesn't work, it just assumes panelType is always 0. Need to figure out how to rearrange the definitions to make this work.
one of the recent commits (b0f7258e039c63e00d4159d0ca9442ab1b628398) doesn't work with my setup: it makes my display flicker as hell. setting different refreshrates after begin() doesn't seem to change anything.
if i comment out the changes of this commit the flickering goes away and setting the refreshrate is working again.
(setup: 96x64, kDmaBufferRows = 4
, kRefreshDepth = 36
, COLOR_DEPTH 24
)
edit: linked the wrong commit. corrected this. i commented out the numLoopsWithoutExit
-stuff to get rid of the flickering.
update: i will play around with the most recent commit (5cd708982cd87b784020fb6dc2fde01f8c94a251) if i can fix the flickering without disabling commit b0f7258e039c63e00d4159d0ca9442ab1b628398. sorry for the confusion.
i think we can close pull request #17 because everything that was added there is now part of sm3.0 anyways?
@mrwastl > one of the recent commits (b0f7258) doesn't work with my setup: it makes my display flicker as hell
Try increasing the value for MAX_MATRIXCALCULATIONS_LOOPS_WITHOUT_EXIT
I'll add some more methods to troubleshoot this tomorrow.
@mrwastl Two improvements to the MAX_MATRIXCALCULATIONS_LOOPS_WITHOUT_EXIT
code, please let me know if this fixes your flickering
@mrwastl nevermind, there are some major unexplained issues with setting refresh rate, I'm working on it now.
@mrwastl Timer weirdness was from the timer overflowing at low refresh rates and from the ticksUsed variable not being large enough to hold the ticks of a slow refresh rate. There is now a minimum refreshRate defined, it's 12FPS for 96MHz, and I'm pretty sure it's higher for you because you're running at a higher clock. You can change the prescaler, 0x02 is /4. If you find it necessary, I'll just add an #ifdef
to set the prescaler based on F_BUS
.
Let me know how it's running now.
@mrwastl
it seems to work fine - with the following exception: kRefreshDepth = 36 is working, kRefreshDepth = 24 crashes
I'm now able to run FeatureDemo at 96x64, kRefreshDepth = 24 with indexedLayer enabled and no crashing.
current status: my setup: hardly any differences to latest sm3.0 (only pin 15 instead of 10, Serial.begin() disabled), cpu = 144mhz.
yep, kRefreshDepth = 24
is working fine, including indexedLayer. i even don't have to set a starting refreshrate any longer.
but when i set kRefreshDepth = 36
(+ disabling indexedLayer because of memory): immediate crash. changing initial refreshrate doesn't help.
@mrwastl I think it's just out of memory. With the same setup except CPU @ 96MHz, it's at 97% of RAM, 1.7k free. Using the debug lines and a logic analyzer I can see none of the ISRs are running. I disabled the scrolling text layer and it runs (just showing a red background, but that's something).
Were you planning on running 36-bit refresh on your display?
uhm, yes. COLOR_DEPTH 24
and kRefreshDepth = 36
.
this combination worked quite nice until the updates from today.
kRefreshDepth = 24
is faster, but the image is nicer with 36.
on the other side: i've tested my mplayer-streaming stuff with kRefreshDepth = 24
and refreshrate = 70:
wow: damn fast. and even no more whining from mplayer telling me that "Your system is too SLOW to play this!". usually my test music video plays around 1 minute longer than it actually would last (even with -framedrop activated). now it needs hardly any extra time (4:06 vs 4:13).
just image: the teensy has to process the data stream (RGB888!) that's coming via usb and to also generate the whole PMW-stuff and everything. quite impressive ...
@mrwastl Glad to hear that your streaming is working well!
I compared yesterday's version to today's, and there's only 4 additional bytes of static memory used, and going through the code, there's not a lot more memory used on the stack. I'm not sure what's causing the problem.
@mrwastl I'll try isolating the code changes to see if there was any one change that had unintended consequences. I might not have time to do that in the next couple days, but if you try it yourself, be careful because my commits were really messy. I accidentally committed unrelated code a couple times then reversed it later, so the code probably won't compile if you check out any one of those intermediary commits.
@mrwastl my schedule changed and I found time to debug this morning. Isolated the crash to use of the new variables in the class: static bool dmaBufferUnderrunSinceLastCheck
, static bool refreshRateLowered
. Moving these above some other variables in the class definition fixed the 96x64@36-bit refresh crash, though I suspect that the sketch is really out of RAM.
I'm going to start wrapping things up for a pre-release, no more new features or (fingers-crossed) major bugs to work on.
@mrwastl Are you using background brightness? If your streaming sketch only uses the background layer, then there's no need. Disabling that feature could be a good way to free up 512 bytes.
i don't get it ...
FeatureDemo: crash with kRefreshDepth = 24
, working with kRefreshDepth = 36
.
my streaming-stuff: working with kRefreshDepth = 24
, crash with kRefreshDepth = 36
.
mem. free with kRefreshDepth = 36
: feature demo: 1792 byte, streaming-stuff: 1500 byte
i hope that we don't have a teensy-crazyness problem: i once had a problem where i had to reorder the assignment of some (6 as far as i remember) variables. initial order: crash. 4-6 above 1-3: no more problem. i still don't have any clue why a stupid reordering changed the behaviour of the teensy (maybe compiler optimization, but i doubt that).
background: yes, i do use that. i can set an option in my library where a user can set the brightness that should be used.
update: if i reduce kDmaBufferRows
from 4
to 3
, kRefreshDepth = 36
is working again with my streaming stuff. after all a mem.problem? (but that doesn't explain the crash in FeatureDemo with kRefreshDepth = 24
)
another observation: the speed-improvement that i've described above (when using kRefreshDepth = 24
and refreshrate = 70) seems to be gone :(
(tested with sm3.0 / 0f07cebf3b1ce45d098a208010ea37cbdf4d4cc6)
@mrwastl I skimmed through your streaming code and it looks like you're just using the background layer and matrix.brightness(). That's global brightness control, changing timers to set the brightness. backgroundLayer.brightness() uses a separate color correction table in RAM to control brightness, just for that layer, so you can have 100% brightness scrolling text, in front of a 10% brightness background if you want. You shouldn't need it, so you can disable it and save 512 bytes (it's on my list to add an option to disable in 3.1)
edit: more details on background brightness
@mrwastl I just put the order of variables in the class definition back to where it crashes. It doesn't crash with kDmaBufferRows = 3
, only with kDmaBufferRows = 4
. That's another confirmation that it's a memory problem.
I think there's less reason to keep the default kDmaBufferRows
value more than the minimum of 2 (one to push to the display, one to update in the background) now that SmartMatrix recovers from buffer underrun better. Try running at 2, and if you see flickering (buffer underrun blanking the display until the buffer has another entry), or the refresh rate is dropping because of repeated underruns, then bump it up.
i'm starting to see ghosts.
now FeatureDemo doesn't work at all :(
no matter if i use kDmaBufferRows = 2/3/4
and kRefreshDepth = 24/36
.
i also tried to use your FeatureDemo directly from your latest commit (only width / height and kDmaBufferRows changed): crash too (but there were no relevant code-changes ?!).
one interesting thing: i accidentally interchanged width and height: and FeatureDemo didn't crash!
(kMatrixHeight = 96
, kMatrixWidth = 64
, kDmaBufferRows = 3
, kRefreshDepth = 36
)
(git show-ref: 291bc36661cb9c353d35144be8200fd604cebee3)
edit: i forgot to note something: kRefreshDepth = 24
works for some seconds but crashes then. kRefreshDepth = 36
crashes immediately.
@mrwastl Sorry, I swapped the order of matrixWidth/Height in FeatureDemo, should have said something.
FeatureDemo 96x64@24-bit refresh crash - didn't test that case before, not a low memory issue for sure.
I see a few ISRs getting run, then it just stops. If I lower the refresh rate, I don't see any ISRs running. I commented out all the code unique to 24-bit refresh and I see the ISRs. I added just the static rgb24 tempRow0
and tempRow1
back in, unused, crash. Tried a bunch more things, led me to add a new tempRow2
, unused, and now I see ISRs. Uncommented the rest of the code, and it's refreshing.
I must be screwing up pointer math somewhere that works for 36-bit color but not 24-bit.
@mrwastl OK, this is weird, putting static rgb24 tempRow2[0];
before or after the other tempRows works, but not a uint8_t array of small or large size. Compiler weirdness, or something else? Need to figure out how to generate a .map file and take a look at it.
@mrwastl Got the .map file (open platforms.txt inside Arduino, add to this line: teensy31.build.flags.ld=-Wl,
-Map={build.path}/output.map,
(or another directory if you don't want it in the frequently changing build.path
There's 4 bytes (pointer?) allocated for tempRow2, so it does shift memory around. Given that shifting memory seems to be key to making things work I tried various sizes for tempRow2. 0 and 1 work, 2 doesn't, 3, 4, and 5 do, 6 doesn't. Now I'm thinking it's not bad pointer math, but bad alignment of something, probably DMA wants its addresses to be aligned in some way. Will dig into that later.
@mrwastl That was a difficult bug to track down. I didn't realize timerPairIdle
needed to be aligned in RAM for DMA to work. It's now stored as DMAMEM
and FeatureDemo (At least DEMO_INTRO) at 96x64 is working for me with 24 and 36-bit refreshDepth.
hmm. maybe there's still at least one side effect:
feature demo now works (with kRefreshDepth = 24
and kRefreshDepth = 36
), but my streaming stuff immediately crashes with all 24 and 36 vs. kRefreshDepth=2/3/4-combinations.
but: it works with kRefreshDepth = 48
and kDmaBufferRows = 3
!
but kRefreshDepth = 48
and kDmaBufferRows = 2
-> crash.
the initialisation is more or less the same as in feature demo (except that i don't allocate and add indexedLayer and scrollingLayer).
the hint with the .map-file sounds interesting. might help for tracing problems like the one that i've described above (variable order).
did some experiments (or better 'some poking around in the dark' :) to isolate the crashes and made the following observation (maybe it gives a hint where to search for the source of the crashes):
i switched back to an older git-revision (where my streaming stuff was working w/o crashes and also faster than now) but where FeatureDemo crashed with most kRefreshDepth/kDmaBufferRows-combinations.
when using kRefreshDepth = 24
FeatureDemo was working for some seconds but crashed then. i played around with the demos (enable/disable, ...) and noticed, that fillScreen() seemed to crash the sketch (the 1st fillScreen() worked, but then -> crash). i tried fillRectangle(0, 1, w, h-1, col) instead -> no more crash (with kRefreshDepth = 24
). i disabled all drawHardware * ()
functions (by inserting an early return): many patterns were processed w/o crash. also kRefreshDepth = 36
succeeded with some demos.
i switched back to the current sm3.0 revision (where FeatureDemo works but my streaming-stuff doesn't): i deactivated all fullScreen()-calls in my streaming-stuff -> no more crash (the only drawing-method that is now used: drawPixel()). the video is finished without a crash (though: the speed-up that i've mentioned at sept 3rd is still gone...).
note: for all tests i've used the FeatureDemo-sketch that belonged to the respective sm3.0 revision. (with width/height/kRefreshDepth/kDmaBufferRows adapted)
@mrwastl Thanks for troubleshooting, I haven't looked at this at all as I've been spending all my time getting 64x64-pixel animated GIFs to play (not an easy problem, requires a lot of RAM). Got it working now.
I'll take a look at those drawHardware functions. I did notice fillScreen wasn't working well in the demo, but didn't realize it was causing crashes.
Try playing around with different settings of refreshRate, keeping in mind that the old refreshRate is somewhere around 10% slower than the more accurate refreshRate now (e.g. your old 100Hz refreshRate setting might produce the same 90Hz as setting refreshRate to 90Hz now). For 64x64-pixel AnimatedGIFs I saw very poor performance in GIF decoding when depending on the SmartMatrix library to lower the refresh rate. It would lower it just enough so there was some CPU time for the application, but not enough to decode GIFs that looked good. I set the refreshRate manually to 90 Hz and now the GIFs run smoothly. In particular I noticed GIFs were playing with lower FPS at 24-bit color than 36-bit color, but when manually setting the frameRate at 90Hz they both looked the same.
yep, you're right. when using refreshrate = 67 instead of 70 with the current version i get the same results (higher FPS-value, no whining mplayer, playing time = 4:13) as described above.
note: i try to add the git ref to every reference to a certain sm3.0 version to make things clearer (e.g. from now 'current' links to the reference that was used for testing). hope that helps.
@mrwastl Definitely helps. So aside from fixing the drawHardware methods, is there anything else you think needs to be in a pre-release version of SM 3.0? I still have improving FeatureDemo for larger displays on my list, but that might have to wait for the actual release of SM 3.0.
@mrwastl @embedded-creations I just ran the sm3_FeatureDemo on a teensy3.1@144MHz onto a 64x64 3mm pitch panel. With kRefreshDepth = 36 I'm seemingly achieving 83Hz refresh rate. Impressive. Very rarely I observe some tearing (just now once during DEMO_DRAWING_ROUNDRECT), but I'm known for being quite sensitive to flicker, and this might also be a hardware issue of my temporary setup (http://sebastian.wangnick.de/20150907_205114.jpg). Is there any way to tweak the timings so as to get a still higher refresh rate, more in the 120Hz range or so (without compromising the 36 bit depth that is needed so that very lowly lit pixels dont start to posterize)?
@wangnick Nice setup! I have an old Logic 8, and want to get one of the new Logic Pros at some point.
As you have a logic analyzer setup, you can turn on the debug pins using DEBUG_PINS_ENABLED
in MatrixHardware_KitV1.h. With DEBUG_PIN_2 (Teensy pin 17) you can see how much time is being spent in the ISR calculating data to shift out, and how much time is left for the sketch to run. That's the code that is limiting the refresh rate. I haven't spent a ton of time optimizing that code so I'm sure there's room for it to run faster.
https://github.com/pixelmatix/SmartMatrix/tree/sm3.0
I'm working on a major revision to the SmartMatrix Library that simplifies the SmartMatrix Class into just refreshing the display, and moves the foreground and background layers into separate Layer classes. Instead of using a unique header file to describe the hardware, the configuration is set in the user's sketch, so you can have one version of the library and use it with different sizes of displays. You can create your own Layer outside of the library - for example I made a Fadecandy Layer class that I used to convert the buffers from a port of Fadecandy to SmartMatrix - and you can make your own stackup of layers, with multiple Foreground layers for example.
This requires a lot more code to set up the classes in the sketch, which I was trying to minimize with the initial release of the library, but I think this more flexible approach supports more use cases. The code is hidden away by using a couple #defines that support the most common use cases, and we can add more. I chose to declare buffers in the sketch instead of using malloc in the classes as I wanted the large buffers to show up in memory usage at the end of compilation, and there's no malloc support for creating DMAMEM buffers.
After separating into classes, refactoring to be more generic (no dependencies on MATRIX_WIDTH/HEIGHT defines) and testing on both 16x32 and 32x32 panels, I found the classes worked with 32x64 with barely any changes. I didn't get a chance to use any code from the >32x32 size pull requests from @ncortot, @GaryBoone, and @mrwastl, though maybe I will when adding support for C-shape chaining.
I have the library in a decent state, and FeatureDemo has been tested on 16x32, 32x32, and 32x64 panels. There's an occasional flicker in the 32x64 I haven't tracked down yet. Only the FeatureDemo example is updated to use the new library, though it should be easy to update the rest. (Except for FastLED_Controller, which will need an update to the FastLED Library with SmartMatrix 3.x support)
It's probably a month or more away from an official release as I'm going to be traveling without a laptop for a couple weeks, and want to add support for more display configurations (especially C-shape paneling), to do more testing, and make some efficiency improvements after I get back.
If there are any other features you'd like to see in the next major release, let's start discussing.
Not yet supported: