Horizontal update tearing


#1

Using two 64x32 modules in 128x32 configuration on a teensy 3.1 running at 120mhz. SmartMatrix v2 and v3

With a very simple example of a single width pixel line the full height of the display(32) scanning left to right at 24/60fps the line is tearing half way up and then again on the top pixel.

Not sure why this is? The buffer is only swapped once the current frame has been shifted out? So cant see why it would be tearing?

Thanks


#2

What is your SmartMatrix refresh rate set to? It doesn’t sync to buffer swaps, so if those are badly out of step it can cause problems. You also don’t need to run at 120MHz (which can potentially cause stability issues) for a DMD replacement, I’m doing 120Hz WPC updates in a similar setup with the Teensy clocked at 96MHz.


#3

Hello eli_curtz

I have seen your project on pinside :smile:
Cant remember thr refresh rate off the top of my head im pretty sure it is either 80/90 i will confirm this. I can drop to 96mhz hopefully this will improve things. I was under the impression the dmd update buffer / current drawing buffer would only swap after a complete dmd update cycle to avoid such tearing issues?


#4

These are my settings.

#define MATRIX_REFRESH_RATE 100
#define COLOR_DEPTH_RGB 24
#define DMA_BUFFER_NUMBER_OF_ROWS 4
#define LATCH_TIMER_PULSE_WIDTH_NS 438
#define MIN_BLOCK_PERIOD_NS 10000


#5

You’re right that it should be happening at row zero for the output. Are you sure the buffer flip is happening at the right time? Are you displaying data from USB or from a pin?

I suppose it’s possible you’re spending too much time in interrupts or something and getting out of sync from that. I’ve made a few optimizations in my fork of SmartMatrix which might help if that’s the issue: https://github.com/ecurtz/SmartMatrix .


#6

I am waiting for a full frame from USB then fire the swapBuffer(true) method. I assumed if mid updating the display the method would block until safe to swap?
I will take a look at your fork see if I can find some clues.

Thanks


#7

This is my test. if you run this do you get a perfectly straight vertical line? Or is it tearing half way?

int cnt = 0;
void loop(){
matrix.fillScreen({0,0,0});
matrix.fillRectangle(cnt, 0, cnt, 31, {255,0,0});
matrix.swapBuffers(true);
cnt++;
cnt%=128;
}

I swapped to 96mhz, i played around with all the different refresh rates and other various settings. Nothing seems to remove the tear. What I find interesting is the tear is exactly where the two sub displays meet. As this display is 1/16 scan its actually doing to scans to create the image (dual at same time) And the tear is where they meet. I have also noticed it looks like the vertical line is very slightly leaning and then gets cut then slightly leans again. Its like the separate scans are going out of sync as they draw each row? Or some thing along these lines?


#8

Sorry for the delayed response. Yes, I get “broken” lines using this code. It might be because you have no delays and it’s executing multiple times per screen refresh? In fact I still get broken lines until I put in a pretty large delay (80ms +) It looks like a bug in the screen refresh code to me.


#9

I think this is caused by the multiplexing in the panel. There are two lines driven at a time, spaced 16 rows apart, and the code scans from top to bottom. If the line is going from right to left and moving one pixel left per frame, pixels (31,15) and (31,31) are lit just before pixels (30,0) and (30,16) are lit.

Try rotating the screen in software before running the same code, you’ll likely see this go away or at least look different at rotations 90 and 270.

Response to a similar report: https://github.com/pixelmatix/SmartMatrix/issues/25#issuecomment-138590730


Horizontal scrolling text off by one pixel (row) when spanning near mid-panel
#10

Wouldn’t that mean that row 0 and row 16 should appear on the same column, since they are refreshed together? It may just be an optical illusion, but row 0 visually seems to be 2 columns behind, then 1-15, then 16-31.


#11

I’ll have to take a look later this week. I’m traveling right now without access to a panel. What you’re describing sounds like an off-by-one bug I’ll need to fix


#12

The row zero thing is because the row increments after the row zero test in matrixCalculations() it could be fixed by moving up the currentRow increment.

    // do once-per-frame updates
    if (!currentRow) {
        ...
    }

    // enqueue row
    if (++currentRow >= matrixRowsPerFrame)
        currentRow = 0;

Still don’t know why the top and bottom half are out of sync, but it almost seems like it might be a hardware issue, given that those are written out at the same time, and it only occurs at higher frame rates.

EDIT: Actually that’s not true, it still happens at very low frame rates, but doesn’t happen at high frame rates with delays. The difference being number of screen refreshes per data change I assume.


#13

Did any one have any luck with this issue (on V3) I had a look at the source code and its a bit over my head (quite new to .c).


#14

I just committed @eli_curtz’s fix:

This fixes the tearing-on-the-first-line issue. It doesn’t fix the tearing-halfway issue, because that’s a result of the panel hardware and there’s no fix for it. You can rotate by 90 or 270, and you’ll see horizontal lines don’t tear. Here’s your test code, updated for SmartMatrix3:

#include <SmartMatrix3.h>
#include <FastLED.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 = 32;        // known working: 32, 64, 96, 128
const uint8_t kMatrixHeight = 32;       // 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_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);

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

void setup()
{
    Serial.begin(9600);

    // Initialize Matrix
    matrix.addLayer(&backgroundLayer); 
    matrix.begin();

    matrix.setBrightness(255);
    matrix.setRefreshRate(255);

    //matrix.setRotation(rotation270);
}

int cnt = 0;
void loop(){
    backgroundLayer.fillScreen({0,0,0});
    backgroundLayer.fillRectangle(cnt, 0, cnt, 31, {255,0,0});
    backgroundLayer.swapBuffers(true);
    cnt++;
    cnt%=128;
}

#15

Ah I see its the middle tear that effects me as I have scrolling text in this area. Not that noticeable at lower scroll speeds but faster really is obvious.

Could you explain a bit more how the hardware causes this issue? Some sort of lag in the shift registers or something? I still do not completely understand what causes the tearing. If you only swap the buffer after a completed scan of the display how can it be out of sync?

Regards
Russell


#16

I explained it above:

Cool project, how are you loading data on the display? I’m guessing you wrote your own scrolling text classes that have multiple colors and scroll vertically (with masking). Looks great!


#17

Ok i sort of understand what’s going on. So if this is an hardware issue do all the big video screens using these panels suffer the same tearing mid panel.

Thanks :slight_smile:

Data is being loaded via a esp8266 module connected to the teensy via uart. It receives the train departure data from a uk train departure board api so its all real time data.

I had the font in byte array form and it is not fixed width so decided to write my own font method to draw my font. It returns the lenth of the text drawn making it easy to draw the next text. I added a vertical mask as well to allow you to scroll it without over writing other graphics above or below.

Another method i added was matrix.stop(); this is needed to literally kill the matrix timer interrupt. I need this when running a dfu routine which updates the flash and the two did not play happy together hehe.

I have not looked at the v3 source in a while is there plans to add (or might be already there?) support for none fixed width fonts. And if the draw text method could return the lenth of drawn string is very useful.

Regards
Russell


#18

Probably at least to some extent. They may refresh the panels at a high refresh rate, probably higher than SmartMatrix, and update the content at a lower refresh rate, e.g. 30fps.

There’s probably some relevant info in this video:


#19

Do you have a writeup or source code shared for your project? I’m starting a new blog on internet connected displays, and your project would be a good fit for a post on the blog.

I added GitHub issues for matrix.stop() and for drawText to return length. If you want to submit either as a pull request or just link to your source (if it’s open source), that would help for sure.

There’s a GitHub issue for font improvements, feel free to take a look and add comments or a link to your source there.


#20

No write up. I can send you some information about the project if you like though.

Yes i can give you the source for the new text methods. I forgot to mention they also include a alignment param which is extremely useful when centering text. I will upload these methods source when i get into work.

Here is the source for my text methods
http://54.148.129.10/source.cpp

Regards
Russell