HUB75/HUB75E - how they really work

I've been working on a project using HUB75 LED matrix panels and was surprised by the lack of information about how they work.

If you've come here to learn about how to hook up panels this is probably the wrong place, this is more about designing hardware and software to drive panels.

A word of warning: HUB75 is a 'flexible' spec, more of a variation on a theme, it's not publicly written down, and different panels have different ideas on what it should be. For example the E address line wanders between pins, the locations of the R, G, and B pins can be swapped etc etc. You need to figure out exactly how your particular panels are wired - and you should buy panels you want to work together from the same supplier all at the same time.

Panel Interface

Panels are connected together with 16 wire cables, each panel has an input cable and an output cable you can connect the output of one panel to the input of another to make wider panels, theoretically limited by your refresh rate. Panels also have a 5V connector, each can draw an amp or two.

The input and output connectors are identical 16-pin IDC sockets the notch is on the middle of one side between pins 4 and 5.

The 'standard' pinout looks like this:

Pixel data is clocked into a panel on the rising edge of every clock - 2 pixels are clocked on every clock, one into the top half of the panel, one into the bottom half.

The number of address lines depends on how many pixels high a panel is. HUB75E simply refers to panels that are 64 pixels high and that need 5 address pins (ie need a pin E). Sadly which pin is used for E varies between panels, usually it's either pin 9 or pin 13.

What's in a panel

Here's an educated guess at what's inside a typical HUB75 panel, the following circuit is repeated 6 times 1 each for the red, green and blue pixels for the top half and again for the RGB pixels on the bottom half of the panel, the demux at the top left may be in common with some or all of the 6 different pixel planes.


Each panel contains 6 shift registers, one for each of the 6 RGB inputs, each shift register is the same length as the number of pixels wide the panel is. On each clock the data moves one pixel from the left of the screen to the right so that after as many clocks as the width of the screen the first pixel clocked is becomes the leftmost pixel and the last pixel clocked in is the rightmost.

Connected to the outputs of each flop is a latch which is loaded and is probably transparent when LATCH is asserted and held when it is low (may be different on different panels). The output of the latch is a current sink (probably a constant current sink matched to the LED) - you can think of it as an open collector/open drain transistor.

At the top left is a demux that converts ABCD(E) into 32 (64) supply lines, it's output is likely 32 (64) PNP/PFET transistors to 5V - at any one time one of those 32 (64) lines is driven allowing one horizontal line of pixels on the top half of the panel and one on the bottom half to be driven from the 6 sets of latches.

When OE is high (unasserted) none of the horizontal line drivers are asserted.

Note: there are no latches on ABCD(E).

How to drive a panel

Here's the generic waveform you need to drive a panel:

Note: 'RGB' are the R1/R2/G1/G2/B1/B2 signals, 'ADDR' are the A/B/C/D/E signals. Don't infer from the diagram that ADDR is related to LATCH, it can change at any time.

Some important things to note (the main reason for this document):

So to break it all down you need to generate signals where: LATCH and ADDR change when OE is disabled (high) and the length of OE for every line is the same.

I have successfully got away with treating OE/LATCH/ADDR as synchronous with the clock and used the following timing.

The big advantage of this is that you don't need a gated clock and OE is always the same length (3 clocks less than the panel width. The potentially scary bit is that you're assuming that the latch inside the panel closes (LATCH signal falls) long enough after the shifted data is clocked that that data is correctly set up on the latch - it may be worth dropping in a buffer to delay LATCH by a few ns.

Dithering for more than 8 colours

All of the above does is tell you how to deliver 3 bits (RGB) to drive an LED - that gives you 8 colours. But all those giant video screens out there are made of HUB75 panels .... the solution is to send each line at a higher rate to PWM each component of each pixel (essentially dithering in time).

For example to display RGB555 (15-bits/pixel) you need to re-display the screen really fast - 2**5 (ie 32) times using each color component value to choose how many of those 32 times the LEDs will be turned on.

For 5 bits per colour component I use the following table:

            0: 0x00000000
            1: 0x00010001
            2: 0x00010101
            3: 0x01010101
            4: 0x01010111
            5: 0x01110111
            6: 0x01111111
            7: 0x11111111
            8: 0x11111115
            9: 0x11151115
            10:0x11151515
            11:0x15151515
            12:0x15151555
            13:0x15551555
            14:0x15555555
            15:0x55555555
            16:0x55555557
            17:0x55575557
            18:0x55575757
            19:0x57575757
            20:0x57575777
            21:0x57775777
            22:0x57777777
            23:0x77777777
            24:0x7777777f
            25:0x777f777f
            26:0x777f7f7f
            27:0x7f7f7f7f
            28:0x7f7f7fff
            29:0x7fff7fff
            30:0x7fffffff
            31:0xffffffff

Gamma Correction

PWM'd LEDS are non-linear, before you feed your dithering engine you'll need to run your data through a gamma table.

Credits

Thanks to Wavedrom for their cool waveform editor

Disclaimer

Please note Moonbase Otago has no connection whatsoever with "Moonbase Holdings LLC" - they are racist scum