Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "deps/rpi-rgb-led-matrix"]
path = deps/rpi-rgb-led-matrix
url = https://github.com/hzeller/rpi-rgb-led-matrix.git
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ endif

all: $(TARGET) $(METALLIB) config.mk

ifeq ($(HAVE_HUB75), 1)
hub75-library:
$(MAKE) -C deps/rpi-rgb-led-matrix/lib CC="$(CC)" CXX="$(CXX)" AR="$(HUB75_AR)" CPU_ARCH_FLAGS= librgbmatrix.a
$(HUB75_LIBRARY): | hub75-library
.PHONY: hub75-library
endif

define INFO
ASFLAGS: $(ASFLAGS)
CC: $(CC)
Expand Down Expand Up @@ -230,7 +237,7 @@ endif

SYMBOL_MAP := -Wl,-Map=output.map

$(TARGET): $(RARCH_OBJ)
$(TARGET): $(RARCH_OBJ) $(HUB75_LIBRARY)
@$(if $(Q), $(shell echo echo LD $@),)
$(Q)$(LINK) -o $@ $(RARCH_OBJ) $(LIBS) $(LDFLAGS) $(LIBRARY_DIRS)

Expand Down
10 changes: 10 additions & 0 deletions Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,16 @@ ifeq ($(HAVE_NETWORK_VIDEO), 1)
OBJ += gfx/drivers/network_gfx.o
endif

ifeq ($(HAVE_HUB75), 1)
DEFINES += -DHAVE_HUB75
INCLUDE_DIRS += -Ideps/rpi-rgb-led-matrix/include
OBJ += gfx/drivers/hub75_gfx.o
HUB75_LIBRARY := deps/rpi-rgb-led-matrix/lib/librgbmatrix.a
HUB75_AR := $(if $(filter %gcc,$(CC)),$(patsubst %gcc,%ar,$(CC)),$(AR))
LIBS += $(HUB75_LIBRARY) -lrt -lm -lpthread
NEED_CXX_LINKER = 1
endif

ifeq ($(HAVE_PLAIN_DRM), 1)
OBJ += gfx/drivers/drm_gfx.o
ifneq ($(HAVE_LAKKA), 1)
Expand Down
1 change: 1 addition & 0 deletions deps/rpi-rgb-led-matrix
Submodule rpi-rgb-led-matrix added at d7eef8
100 changes: 100 additions & 0 deletions docs/hub75.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# HUB75 RGB LED matrix video driver

RetroArch can render software-core video directly to HUB75 RGB LED panels
connected to a Raspberry Pi GPIO header. The driver uses the bundled
`rpi-rgb-led-matrix` submodule and does not require X11, Wayland, DRM, or a
desktop session.

## Build on Raspberry Pi

Initialize submodules, enable the driver, and build RetroArch:

```sh
git submodule update --init --recursive
./configure --enable-hub75
make -j4
```

Select the driver in `retroarch.cfg`:

```ini
video_driver = "hub75"
menu_driver = "rgui"
```

The driver uses nearest-neighbour scaling with configurable aspect handling,
supports rotation, and accepts RGB565 and XRGB8888 software frames. Hardware
rendered cores are not supported because they do not provide a CPU-readable
framebuffer.

## Panel configuration

Configuration uses environment variables so panel wiring can be changed
without adding hardware-specific values to `retroarch.cfg`:

| Variable | Meaning |
| --- | --- |
| `HUB75_ROWS` | Rows per panel (commonly 32 or 64) |
| `HUB75_COLS` | Columns per panel (commonly 64) |
| `HUB75_CHAIN` | Panels daisy-chained horizontally |
| `HUB75_PARALLEL` | Parallel output chains |
| `HUB75_BRIGHTNESS` | Brightness from 1 to 100 |
| `HUB75_SCALING` | Scaling mode: `fit`, `fill`, `stretch`, or `integer` |
| `HUB75_PWM_BITS` | PWM colour depth from 1 to 11 |
| `HUB75_GPIO_SLOWDOWN` | GPIO slowdown, usually 1-4 on newer Pi models |
| `HUB75_GPIO_MAPPING` | Pin mapping, e.g. `regular` or `adafruit-hat` |
| `HUB75_PIXEL_MAPPER` | Pixel mapper string for unusual panel layouts |
| `HUB75_RGB_SEQUENCE` | Physical channel order, e.g. `RBG` |
| `HUB75_PANEL_TYPE` | Panel initialization type such as `FM6126A` |
| `HUB75_MULTIPLEXING` | Multiplexing mapper number |
| `HUB75_ROW_ADDR_TYPE` | Row addressing type |
| `HUB75_RP1_PIO` | Set to 1 to use RP1 PIO on Raspberry Pi 5 |

Example for one 64x64 panel:

```sh
sudo env HUB75_ROWS=64 HUB75_COLS=64 HUB75_GPIO_SLOWDOWN=4 \
./retroarch -v
```

Scaling modes:

- `fit` preserves the complete image and adds black bars when necessary. This
is the default.
- `fill` preserves aspect ratio and crops the image symmetrically to fill the
entire matrix.
- `stretch` uses every LED without cropping, but may distort the image.
- `integer` uses an integer enlargement factor, or samples every Nth source
pixel when the source is larger than the matrix. It keeps pixels uniform and
shows the complete image, but may leave larger black borders.

For a single 128x64 panel, `fill` is generally the most useful game mode:

```sh
sudo env HUB75_ROWS=64 HUB75_COLS=128 HUB75_SCALING=fill \
HUB75_RP1_PIO=1 ./retroarch -v
```

GPIO initialization normally requires root. Run RetroArch locally on the Pi;
timing-sensitive HUB75 output should not be driven through a remote GPIO
bridge.

## Cross-compile from macOS without Docker

With an `aarch64-linux-gnu` cross toolchain installed:

```sh
git submodule update --init --recursive
OS=Linux ./configure --host=aarch64-linux-gnu --enable-hub75
make -j8 OBJDIR_BASE=obj-linux-arm64
```

Additional RetroArch features may require a Raspberry Pi sysroot. Disable
features you do not need or supply their ARM64 headers and libraries through
the toolchain/sysroot; the bundled HUB75 library itself is built with the same
`CC`, `CXX`, and `AR` selected by RetroArch.

Setting `OS=Linux` is required when running RetroArch's configure script on
macOS; otherwise it identifies the build machine as Darwin while testing the
Linux cross compiler. A separate `OBJDIR_BASE` also prevents native macOS and
ARM64 dependency files from colliding.
Loading
Loading