examples/parallel/tufty: add Displayer, faster bus, animated demo - #58
conejoninja merged 1 commit into
Conversation
e9d5aca to
8ff98bd
Compare
|
@conejoninja this PR adds Display support -- note the duplication of the Displayer interface, I dunno if you want to take a dependency there -- as well as some demos. Please let me know if you want me to break it out into smaller pieces -- just take the Display interface, etc. |
|
Is Displayer really needed? For the example I think it can be removed. Should we create a driver in https://github.com/tinygo-org/drivers for this? If so, a new one like st7789-pio-parallel or try to use the existing driver and adding a new bus? |
|
Hmmm I hadn't looked at this PR before merging the other that also adds Display method 😅 As for drivers, I'm interested in future drivers evolving towards a more performant API which means reformulating tinygl and the display API to be more like this https://github.com/soypat/tinygo-seeed-grove/tree/main/drivers/ssd1306 |
Implement SetPixel and Display on ST7789 backed by a fixed [320*240*2]byte framebuffer in .bss (~154KB, ~58% of RP2040 SRAM). The buffer is stored high-byte-first so it streams straight to the panel (RAMCTRL=0xC0, big-endian) via Tx8 with no per-frame byte swap. Add a compile-time assertion that ST7789 satisfies the local Displayer interface, whose signatures match tinygo.org/x/drivers.Displayer so downstream code can substitute that interface trivially without adding the dependency here. Expose the PIO bus rate as a top-level busBaud constant. The PIO program is three instructions long, so the state machine clock runs at 3 * busBaud. The ST7789 8080-II parallel interface has a 66ns minimum write cycle (~15.15 MHz); run at 15 MHz, verified visually clean on Tufty 2040 hardware. Replace the solid blue fill in main() with a cycling animated demo: bouncing rectangles, a Mandelbrot fractal zoom (fixed-point Q6.26), and a sin-LUT plasma. Each demo reports measured FPS over UART. Measured on Tufty 2040 at 15 MHz: bouncing rects ~40 FPS (bus-saturated full-frame transfer), plasma ~14 FPS, mandelbrot ~0.8 FPS.
8ff98bd to
30f787b
Compare
|
@conejoninja @soypat not ignoring your comments, just rubbing my chin on what this might look like. In my brief soirée I’ve found displays that need a frame buffer larger than sram — presto, that’s you — frame buffers that can be upscale on the fly — I have some scanvideo demos to publish — and frame buffers connected to devices that are to slow to matter — badger and st7789 over spi. In the middle is the tufty with its Pio parallel display, which is both performant and memory hungry. I don’t have enough experience to know how the tufty generalises to other displays. Istm that anything smaller/slower benefits from the current set pixel api where the displays GRAM holds the goods. Maybe a middle ground is to promote ST7789-parallel to drivers as is and see where their forks take it. For example, I have a branch where I yolo blocking tx because I know my frame time is longer than the 10ish ms it takes to push the fb over dma. |
|
I'm rooting for this to be promoted to drivers ... because I want to add the tufty to badges firmware 🤣 And I don't want to start a discussion here, In my opinion there could be different flavors of drivers, for example the ssd1306 uses a framebuffer and that's too big for a attiny (like gopherArcade) so I needed a bufferless version. I also consider tinygl learning step a bit to high for beginners, so again, I'm in favor of having multiple versions/flavors like driver, driver-performance, ... In resume, if it works (and it follows as much as possible the API of similar drivers ), I'm green for it |
|
So this looks good to me, do we want to merge or are we thinking some other thing with the promotion? (I assume you are talking of tinygo-org/drivers) |
|
Merging now this and then we could re-use the code to create the driver in @davecheney since you are the author, do you want to create the driver or are working on other displays? |
I'm working on a branch now to bring the st7789 over to drivers/ |
Approach
ST7789now implements a small localDisplayerinterface (Size,SetPixel,Display) backed by a static.bssframebuffer ([320*240*2]byte, ~154 KB, high-byte-first RGB565). A compile-time assertion pins the interface. No dependency ontinygo.org/x/drivers— deliberately keepinggo.modzero-require; the interface is trivial and matching upstream can happen later if we ever pull the driver into the module.[]byteand streamed viaTx8rather than[]uint16/Tx16, becausepiolib.NewParallelusesBitsPerPull: 8and shifts LSB-first, so 16-bit words would silently drop the high byte. Storing high-byte-first +Tx8matchesRAMCTRLbyte order.busBaudis now a named constant at 15 MHz. The PIO parallel program is 3 instructions, so PIO SM clock = 3 x baud = 45 MHz. On RP2040 that gives an actual WR cycle of ~66.6 ns, just inside the ST7789 8080-II 66 ns minimum, and confirmed visually on hardware.math, and a sin-LUT plasma) under all four rotations, printing per-run FPS over UART.Notes for review
Display()sends the full framebuffer as a singleRAMWRstream, followed by a 10us settle beforedc.High(). This matches the sameTx8-return / WR-edge race we fixed incommand()andFillRectanglein examples/parallel/tufty: fix ST7789 parallel display init #55:helperPushUntilStallreturns on TxStall, which fires a couple of PIO cycles before the last WR falling edge propagates through the pads, so flipping DC immediately can corrupt the trailing byte.CS/DC/RDoutputs at idle-high) is moved beforepiolib.NewParallelinmain(), and removed fromCommonInit. This closes an intermittent init race where PIO SM startup would clock zeroed OSR contents onto floating pins while CS was still an input, causing the panel to occasionally latch stray bytes and refuse to init.configureDisplayRotationend-to-end. FPS is unchanged vs the pre-rotation-cycling tip.Verification
Hardware verified on a real Tufty 2040:
gofmt -l .clean.tinygo build -target=tufty2040succeeds.go.modremains zero-require.