pixelmatix / SmartMatrix

SmartMatrix Library for Teensy 3, Teensy 4, and ESP32
http://docs.pixelmatix.com/SmartMatrix
611 stars 161 forks source link

Reduce panel data clock (<5MHz) for Bad Panels #58

Closed mhungerford closed 3 years ago

mhungerford commented 5 years ago

I have some panels from Meiyad that in one batch worked, but in the new batch the image slowly gets worse from panel to panel. Meiyad reproduce the issue, and found a workaround was to slow the data clock to < 5MHz.

I have been tweaking the values in SmartMatrix_Impl.h and MatrixHardwareKit.h, as well as modifying the F_BUS and F_CPU speeds (by providing it both as a PLATFORMIO_BUILD_FLAG and platformio.ini board_f_cpu rate, the newest platformio overrides F_CPU using a default board_f_cpu value).

I have been able to reduce the CPU speed to reduce the distortion, but cannot get low enough to avoid the issue, as going too low breaks USB. I have been checking against the values in mk20dx128.c to use F_CPU and F_BUS rates that are supported.

Using an oscilloscope, it seems the clock value is based on the F_CPU rate and not the F_BUS rate, but is oddly F_CPU / 18. Not sure where the 18 comes from, but if I could increase that, I could leave the CPU rate alone and just slow the data clock to the panel.

mhungerford commented 5 years ago

Meiyad says that they are using a new batch of ICs that exhibit this issue even with their own controller.

These panels are 32x32, there are 3 of them in series (32ROW_MOD8SCAN).

embedded-creations commented 5 years ago

Try uncommenting this line:

https://github.com/pixelmatix/SmartMatrix/blob/master/src/SmartMatrix_Impl.h#L622

embedded-creations commented 5 years ago

doh, that's already uncommented (I was going from memory from the years where it was just a debug option)

embedded-creations commented 5 years ago

Change the value of that line from 0x02 to 0x03, and it should stall the DMA engine for 8 cycles instead of 4, hopefully dropping the HUB75 CLK speed in half

mhungerford commented 5 years ago

That makes every pixel flicker white-ish, the original image is there the same as before, like extra data is being latched.

mhungerford commented 5 years ago

Here are the scope traces, first is the good panels, second is the bad panels where the data is skewed by the bad ICs (captured from clk and R2 pins out from 3rd panel). These were captured while we were running with F_CPU=192000000 (192MHz). In the good panels, clock and R2 transition at same time. In the bad panels, eventually it shifts so the R2 occurs just after the clock is transitioning again. Same for all other colors.

good_panel bad_panel

mhungerford commented 5 years ago

Here is the original asset: testing

Here is how it looks on the hardware, notice the corrupted data between panels 1-2 and 2-3.
testing_logo_orig

And here is the panels using the TCD->CSR dma slowdown 0x3: testing_logo_dma3

mhungerford commented 5 years ago

These panels have an odd internal order, which is why the bad data is from the next panel over, and upside down. Here is a pic from the previous good batch of panels: testing_logo_good

embedded-creations commented 5 years ago

What happens if you use the stock SmartMatrix Library (without your F_CPU etc changes) and just change that value I mentioned from 0x02 to 0x03?

mhungerford commented 5 years ago

Same Problem. Looks identical to when F_CPU/F_BUS is modified.

mhungerford commented 5 years ago

Ah, I needed to increase the LATCH_TIMER_PULSE_WIDTH_NS, now I can use 0x03 for TCD->CSR. It helps, but still slightly off. Reduced the problem.

embedded-creations commented 5 years ago

Glad you found that, I meant to tell you that this morning, but forgot before I got to my email later in the day

embedded-creations commented 5 years ago

You probably also want to change PANEL_32_PIXELDATA_TRANSFER_MAXIMUM_NS as that's related to the panel CLK speed. You may want to change this as well LATCH_TO_CLK_DELAY_NS

mhungerford commented 5 years ago

Here is that image: testing_logo_0x03

mhungerford commented 5 years ago

Odd, DMA_UPDATES_PER_CLOCK is 2, but I cannot seem to make it 1 without it breaking. Otherwise this should also impact the rate, correct?

embedded-creations commented 5 years ago

It needs to be 2, there are two updates, one to set the clock high, one to set the clock low.

mhungerford commented 5 years ago

So using 0x03 for TCD->CSR and lowering the CPU speed gets it pretty close. Is there anything else I can do to slow down the panel clock rate?

I'm surprised that the speed is based on the CPU and not the BUS speed, as I thought the DMA rate was the BUS rate.

embedded-creations commented 5 years ago

Sorry, I'm out of ideas.

Doesn't lowering the CPU speed also lower the bus rate?

dbenner-cpi commented 5 years ago

Is there a way to reduce the clock duty cycle?

embedded-creations commented 5 years ago

not easily, it would involve writing code to insert more data (e.g. 2x CLK low cycles, 2x CLK high cycles) into the data buffer that's shifted out to GPIO, and it would multiple the amount of data used for refresh.

mhungerford commented 5 years ago

So the mk20dx128.c provides the configurations for F_CPU, and if coded to support it, can have the F_BUS as a lower (supported) multiple. Some already have a few options, I added a few for testing. The hope was to keep the processing power, while just reducing the bus, mainly used in this case for the Panel display. So things like GIF processing would still be ok.

mhungerford commented 5 years ago

Thanks for the help, the SmartMatrix code really is brilliant. Amazing to see the DMA controller leveraged this way, and the templated function and graphic buffers is a pretty clever optimization.

Will tweak out the CPU and timings with the CSR 0x03, see if its enough for these messy panels.

embedded-creations commented 5 years ago

I wouldn't recommend using it as the project isn't released yet and I'm not actively working on it, but the SmartMatrix Library ESP32 port lets you select more arbitrary clock speeds because of the way the ESP32 DMA controller functions. It's a bit less of a hack than the Teensy, and more efficient:

https://community.pixelmatix.com/t/smartmatrix-library-esp32-port/272

mhungerford commented 5 years ago

Are you saying that port still works on the Teensy? I tried your teensylc branch, but it removed hooks I needed for re-arranging the incorrectly layed out sections... testing_logo_jumble

mhungerford commented 5 years ago

In the SmartMatrix_Impl.h, I swap segments in the loadMatrixBuffers function:

if (optionFlags & SMARTMATRIX_OPTIONS_JUMBLE) {
           int idx = 0;
           int offset = 0;
           int segment = i / 16;

           // Horrible hack to re-arrange 16x32 segments from
           // 0 4 2
           // 3 1 5
           // 
           // to
           // 0 2 4
           // 1 3 5
     switch (segment) {
           case 0:
              idx = 0; // 12B
              offset = idx * 16 + (i%16);
              temp0red = tempRow1[offset].red;
              temp0green = tempRow1[offset].green;
              temp0blue = tempRow1[offset].blue;

              idx = 6; // 11B
              offset = idx * 16 + (i%16);
              temp1red = tempRow1[offset].red;
              temp1green = tempRow1[offset].green;
              temp1blue = tempRow1[offset].blue;
              break;
           case 1:
              idx = 1; // 12D
              offset = idx * 16 + (i%16);
              temp0red = tempRow1[offset].red;
              temp0green = tempRow1[offset].green;
              temp0blue = tempRow1[offset].blue;

              idx = 7; // 11D
              offset = idx * 16 + (i%16);
              temp1red = tempRow1[offset].red;
              temp1green = tempRow1[offset].green;
              temp1blue = tempRow1[offset].blue;
              break;
... through case 11
}
embedded-creations commented 5 years ago

It should still work on the Teensy but code has been refactored a lot. It doesn't have any major Teensy-specific improvements, and won't help with your <5MHz CLK requirement. I was just mentioning that on the ESP32 the DMA clock rate (really I2S clock rate) can be set easily, and would be able to drop below 5MHz.

mhungerford commented 5 years ago

No luck, unfortunately. The DMA 0x03 trick helped, and changing the clock rate helps, but still can't get rid of all the artifacts. I would be interested in how to do the clk data delay, to decouple the data rate from the CPU speed some more. @embedded-creations - I sent you a PM.