Skip to content

unor4matrix: add LED matrix driver for Arduino UNO R4 WiFi - #941

Open
numbata wants to merge 1 commit into
tinygo-org:devfrom
numbata:feat/unor4matrix
Open

numbata wants to merge 1 commit into
tinygo-org:devfrom
numbata:feat/unor4matrix

Conversation

@numbata

@numbata numbata commented Nov 6, 2026 •

Copy link
Copy Markdown

Summary

Add support for the UNO R4 WiFi's built-in 12x8 monochrome LED matrix. Device implements drivers.Displayer. Like the sibling UNO Q driver, manual Display performs a complete scan and returns with all lines floating.

SetPixel / ClearDisplay / LoadFrame
  Display
    scan 96 fixed slots
    return with all lines floating

Synchronous GPIO scanning works without reserving a peripheral timer or IRQ. One 12-byte image is scanned directly, with no persistent cursor or previous-pair state. Unlike UNO Q, dark pixels retain their nominal 100 us slots. GPIO and scheduler overhead still affect the complete scan rate. Low-level scan operations remain private. The GPIO HAL and NewOnboard helper keep native tests independent of machine.Pin; the two-operation HAL is local rather than importing another display driver. Configure has no options because rotation and brightness control are outside this version. The R4 matrix lines are not consecutive, so NewOnboard uses an explicit pin list rather than a base pin. Out-of-bounds writes are ignored, matching microbitmatrix and allowing graphics to be clipped. Like UNO Q, ClearDisplay clears the drawing buffer. GetPixel is omitted pending a separate discussion of the differing readback APIs used by matrix drivers.

Conway's Life demo

tinygo flash -target=arduino-uno-r4-wifi ./examples/unor4matrix/life

A glider runs on a wrapping 12x8 B3/S23 grid with 300 ms generations. Each Display call blanks the lines before Life computes the next generation. A checkerboard example is also included. Both examples use repeated Display calls and the default tasks scheduler. No core changes are needed.

With TinyGo 0.44 and -scheduler=none, short sleeps may wait for the 1 ms SysTick, reducing the scan rate to about 10 Hz. The provided manual timing requires the default tasks scheduler. Foreground work can still pause refresh.

Evidence

  • Before: UNO Q has matrix support, but UNO R4 WiFi does not. After: both new examples build for arduino-uno-r4-wifi.
  • Display returns ErrNotConfigured before successful Configure without touching GPIO.
  • GPIO traces check complete-frame scanning, pair blanking, repeated Configure and drawing changes. A dark-frame test checks the minimum duration of 96 slots.
  • make unit-test passed all 37 packages selected by the Makefile.
  • go vet ./unor4matrix, make fmt-check, and git diff --check passed.
  • The existing smoke runner passed both new example commands. The complete cross-target smoke suite was not run locally.
  • Tests cover Arduino frame packing, GPIO sequencing, fixed dark slots, blanking and colors/bounds.

Both examples were tested on a real Arduino UNO R4 WiFi after the final single-buffer scan simplification:

  • Checkerboard displays correctly.
  • Conway's Life runs correctly.

Merge Danger

Door: two-way.

Blast Radius: isolated.

Adds one driver, two examples and two smoke commands. No core changes or new dependencies. Callers must repeat Display to refresh.

Drive the UNO R4 WiFi's 12x8 charlieplexed matrix through eleven GPIO
lines, with Arduino packed frames and a host-buildable GPIO adapter.

Use synchronous GPIO scanning without reserving a peripheral timer or IRQ.
Display scans one 12-byte image through all 96 slots and floats each active
pair after its slot. Dark slots retain their delay. Configure has no Config
argument because this driver currently has no configuration options.
The examples use the default tasks scheduler and include Conway's Life.
@numbata

numbata commented Nov 6, 2026

Copy link
Copy Markdown
Author

Conway's Life running on a real Arduino UNO R4 WiFi with the example included in this PR.

unor4matrix-life.mp4

@numbata

numbata commented Nov 6, 2026 •

Copy link
Copy Markdown
Author

While comparing the matrix drivers, I noticed that unoqmatrix.GetPixel returns color.RGBA, while microbitmatrix.GetPixel returns bool. The Displayer interface does not specify a pixel readback method.

Would it be useful to agree on a common readback API for these drivers in a separate follow-up? That could also clarify how monochrome pixels, coordinates outside the drawing area and rotation should be handled. This PR leaves out GetPixel until there is a clearer convention to follow.

There is also some shared charlieplex plumbing: CharlieplexPin and the 11-line count are duplicated between unoqmatrix and unor4matrix. Would a small shared internal package be useful when a third board needs this pattern? The pin count could remain specific to each board. This can be a separate follow-up rather than expanding this PR.

@numbata
numbata marked this pull request as ready for review November 6, 2026 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant