# Framebuffer on psram

**URL:** <https://forum.clockworkpi.com/t/framebuffer-on-psram/16667>\
**Category:** PicoCalc\
**Created:** [April 9, 2025, 7:56pm UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667 "2025-04-09T19:56:57Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ben](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/ben/32/11799_2.png) [@Ben](https://forum.clockworkpi.com/u/Ben)\
**Post date:** [April 9, 2025, 7:56pm UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/1 "2025-04-09T19:56:57Z")

</div>

Has anyone succeeded in setting up a framebuffer on psram?

---

<div class="post-metadata">

**Author:** ![JackCarterSmith](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/jackcartersmith/32/11509_2.png) [@JackCarterSmith](https://forum.clockworkpi.com/u/JackCarterSmith)\
**Post date:** [April 11, 2025, 9:34am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/2 "2025-04-11T09:34:41Z")

</div>

Never used external ram before, it would be a good start to use the PSRAM supplied in the PicoCalc!

The chip used is the ESP-PSRAM64H ([https://cdn-shop.adafruit.com/product-files/4677/4677\_esp-psram64\_esp-psram64h\_datasheet\_en.pdf](https://cdn-shop.adafruit.com/product-files/4677/4677_esp-psram64_esp-psram64h_datasheet_en.pdf)).  
I found a lib for the [RP2040](https://github.com/polpo/rp2040-psram) and [RP2350](https://github.com/FreddyVRetro/pico_psram/). But probably need some adjustment to work with the hardware configuration of the PicoCalc.  
Also sparkfun do a [lib](https://github.com/sparkfun/sparkfun-pico) implement malloc/free/etc. functions to support 2350 SRAM and PSRAM. It uses a [tlsf implementation](https://github.com/espressif/tlsf) from Espressif.

I’ve read somewhere (and confirmed by the RP2350 architecture) that the PSRAM and external Flash share the same QSPI bus. Depending on the software implementation, this can lead to slowdowns or even a crash.

I’d like to try writing the framebuffer with the CPU (or 2nd core) in PSRAM. And let the DMA/PIO do the PSRAM\<=\>LCDSPI transfer.

---

<div class="post-metadata">

**Author:** ![thwill](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/thwill/32/9466_2.png) [@thwill](https://forum.clockworkpi.com/u/thwill)\
**Post date:** [April 11, 2025, 9:45am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/3 "2025-04-11T09:45:23Z")

</div>

There has been discussion on [https://www.thebackshed.com/forum/ViewForum.php?FID=16](https://www.thebackshed.com/forum/ViewForum.php?FID=16) and (my understanding is that) the PicoMite maintainer has said that the PSRAM is too slow to be used as a PicoMite framebuffer.

YMMV,

Tom

---

<div class="post-metadata">

**Author:** ![Ben](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/ben/32/11799_2.png) [@Ben](https://forum.clockworkpi.com/u/Ben)\
**Post date:** [April 11, 2025, 9:59am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/4 "2025-04-11T09:59:51Z")

</div>

Yeah, the helloworld example in the PicoCalc repo has a benchmark of the PSRAM and its top performance with the pico1 is 900KB/s, which is way too low for what is necessary for 320x320x3 at 60fps (18 MB/s). Even rgb565 at 30fps is 6 MB/s.

Maybe PSRAM can be used as backbuffer with a selective update of small regions.

---

<div class="post-metadata">

**Author:** ![DigitalDreams](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/digitaldreams/32/16007_2.png) [@DigitalDreams](https://forum.clockworkpi.com/u/DigitalDreams)\
**Post date:** [April 11, 2025, 10:35am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/5 "2025-04-11T10:35:34Z")

</div>

Milk-v duo (SG2002). 64Mb to 256Mb ddr ram  
Luckfox Lyra (RK3506G2). 128Mb dd3 ram.

If only we could install Picomite/MMBasic on the Luckfox… maybe the Milk-v ??

---

<div class="post-metadata">

**Author:** ![Ben](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/ben/32/11799_2.png) [@Ben](https://forum.clockworkpi.com/u/Ben)\
**Post date:** [April 11, 2025, 11:29am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/6 "2025-04-11T11:29:07Z")

</div>

There is another forum post about the Lyra. I have one but I have not been able to make it work yet.

---

<div class="post-metadata">

**Author:** ![JackCarterSmith](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/jackcartersmith/32/11509_2.png) [@JackCarterSmith](https://forum.clockworkpi.com/u/JackCarterSmith)\
**Post date:** [April 11, 2025, 7:15pm UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/7 "2025-04-11T19:15:21Z")

</div>

PSRAM with rp2040 seem to be useless indeed…

But I saw some peoples got ~25/20 MB/s on 32-bit uncached R/W with [non-overclocked rp2350](https://forums.raspberrypi.com/viewtopic.php?t=384076&sid=dd356b9730d4656a7a79b89e43e8c3f8&start=25#p2297080), 38/26 MB/s after overclocking and some tuning!

---

<div class="post-metadata">

**Author:** ![JackCarterSmith](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/jackcartersmith/32/11509_2.png) [@JackCarterSmith](https://forum.clockworkpi.com/u/JackCarterSmith)\
**Post date:** [April 23, 2025, 8:34pm UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/8 "2025-04-23T20:34:30Z")

</div>

After a deep reading of the screen datasheet, the max framerate reachable in theory is about 12 Hz.  
That in the case you want to push the entire 320x320x16 framebuffer of course.

The PSRAM shouln’t be the bottleneck, neither on rp2040, nor on rp2350…

Maybe we can do some “tile-ing” of the screen areas, pushing only the updated ones. We can double the framerate just by updating the half of the pixels!

---

<div class="post-metadata">

**Author:** ![1more](https://avatars.discourse-cdn.com/v4/letter/1/c89c15/32.png) [@1more](https://forum.clockworkpi.com/u/1more)\
**Post date:** [April 24, 2025, 7:18am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/9 "2025-04-24T07:18:05Z")

</div>

I think you’re missing one point: the speeds you mention here apply to cases where PSRAM is connected via QSPI.

However, the QSPI lines of the RP2350 MCU chip are not exposed through the 40-pin header on the Pi Pico 2/2W boards. So, whatever is available on the PicoCalc mainboard definitely can’t be connected to that QSPI interface.

As of now, I believe only the Pimoroni Pico Plus 2/2W boards have a PSRAM chip on the board, and it’s connected through QSPI.

---

<div class="post-metadata">

**Author:** ![JackCarterSmith](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/jackcartersmith/32/11509_2.png) [@JackCarterSmith](https://forum.clockworkpi.com/u/JackCarterSmith)\
**Post date:** [April 24, 2025, 10:07am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/10 "2025-04-24T10:07:52Z")

</div>

@1more And yes indeed, the PSRAM on the picocalc is only connected on standard GPIO… (no doubt because it was designed for rp2040).  
This invalid the speed values I said at the beginning.

At this point, rather than remaking the picocalc PCB, I’m thinking of making a “yet another pico custom board”. In order to connect the screen in parallel mode (through a direct flex interface).

But first, let’s receive it and do some tests!

---

<div class="post-metadata">

**Author:** ![1more](https://avatars.discourse-cdn.com/v4/letter/1/c89c15/32.png) [@1more](https://forum.clockworkpi.com/u/1more)\
**Post date:** [April 24, 2025, 10:35am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/11 "2025-04-24T10:35:54Z")

</div>

Just to make sure we’re on the same page:

the fact that PSRAM on PicoCalc is connected to the Pico’s GPIO instead of QSPI isn’t a limitation of PicoCalc itself, but rather a limitation of Pico-compatible modules. As of now, there are no mass-produced 40-pin modules based on the RP2040 or RP2350 that expose the QSPI lines on the 40-pin header.

This is because these modules are typically designed to be pin-compatible with the Raspberry Pi Pico 1/2, which didn’t expose the QSPI lines in the first place.

And if you find or create a module that does expose the QSPI lines on 40-pin header, it will, by definition, no longer be pin-compatible with the rest of the Pico-based boards.

---

<div class="post-metadata">

**Author:** ![JackCarterSmith](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/jackcartersmith/32/11509_2.png) [@JackCarterSmith](https://forum.clockworkpi.com/u/JackCarterSmith)\
**Post date:** [April 24, 2025, 1:08pm UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/12 "2025-04-24T13:08:29Z")

</div>

I can see that it’s a question of keeping pins-compatible as possible, which is valid for picocalc main board side.

I can embbed the PSRAM like the Pimoroni Pico Plus 2 does, this keep the pins-out compatible but makes the picocalc’s PSRAM useless (and adds electricity consumption). A ‘dedicated’ pico-card may sacrifice compatibility (only for the custom pico-board) for efficiency, and avoid doing a remake of the picocalc mainboard (too much rework just for testing).

However, other cards like Luckyfox or Milk-V, cannot exceed 20-25 MHz of SPI either given the screen specs… The QSPI PSRAM of the Pimoroni Pico Plus 2 or others will not be useful (for framebuffer) as long as the TFT-SPI bandwidth is not increased.

---

<div class="post-metadata">

**Author:** ![JackCarterSmith](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/jackcartersmith/32/11509_2.png) [@JackCarterSmith](https://forum.clockworkpi.com/u/JackCarterSmith)\
**Post date:** [October 22, 2025, 5:55pm UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/13 "2025-10-22T17:55:13Z")

</div>

I just found that “raylib” have implemented an OpenGL 1.1 software renderer in their latest commits.

It aim to be used on limited hardware which lack GPU or others accelerators. Ideal for pico in others words!

Apart from OpenGL management (windowInit, draw, etc.), the only thing left to manage would be the framebuffer switch and sending it to the screen.

> <https://github.com/raysan5/raylib/pull/4832>
>
> This PR aims to work on the integration of software rendering support into \`rlgl…\`, through an external header \`rlsw.h\`
> 
> I give to @raysan5 the privilege of choosing the name if \`rlsw\` doesn't suit him.
> 
> Additionally, the header is delivered with an MIT license in my name. I also leave the choice of the license to @raysan5. Consider this project as a donation to the community; I will not redistribute it on my side.
> 
> This header \`rlsw.h\` is intended to provide, for now, all the functionalities offered by \`rlgl.h\` for OpenGL 1.1.
> 
> Currently, rendering is performed to a framebuffer that supports multiple formats, selectable at compile time:
> 
> \- \*\*Color Buffer:\*\*
> - RGB - 8-bit (3:3:2)
> - RGB - 16-bit (5:6:5)
> - RGB - 24-bit (8:8:8)
> 
> \- \*\*Depth Buffer:\*\*
> - D - 8-bit (unorm)
> - D - 16-bit (unorm)
> - D - 24-bit (unorm)
> 
> For the rest, I'll leave you to check the checklist.
> 
> If you notice any features that should be implemented and are missing from the checklist, please mention them or edit the post if you can.
> 
> \*\*note\*\*: This PR currently only contains the header. I will work on the integration once the checklist is complete and a decision has been made on how to integrate it into raylib.
> 
> \_\_\_\_
> 
> \## \*\*Feature Checklist\*\*
> 
> \### \*\*Clipping\*\*
> 
> \- \[x\] \*\*Point Clipping\*\*
> \- \[x\] \*\*Line Clipping\*\*
> \- \[x\] \*\*Triangle Clipping\*\*
> \- \[x\] \*\*Quad Clipping\*\*
> 
> \### \*\*Rendering\*\*
> 
> \- \[x\] \*\*Point Rendering\*\*
> \- \[x\] \*\*Line Rendering\*\*
> \- \[x\] \*\*Triangle Rendering\*\*
> \- \[x\] \*\*Quad Rendering\*\*
> \- \[x\] \*\*Polygon Modes\*\*
> \- \[x\] \*\*Point Width\*\*
> \- \[x\] \*\*Line Width\*\*
> 
> \### \*\*Texture Support\*\*
> 
> \- \[x\] \*\*All Uncompressed Texture Formats Supported by Raylib\*\*
> \- \[x\] \*\*Texture Minification / Magnification Checks\*\*
> \- \[x\] \*\*Bilinear Filtering\*\*
> \- \[x\] \*\*Texture Wrap Modes with Separate Check for S/T\*\*
> 
> \### \*\*Vertex Arrays\*\*
> 
> \- \[x\] \*\*Vertex Arrays Support\*\*
> \- \[x\] \*\*Direct Primitive Drawing Mode\*\*
> \- \[x\] \*\*Matrix Stack Support\*\*
> 
> \### \*\*Misc\*\*
> 
> \- \[x\] \*\*GL-like Getter Functions\*\*
> \- \[x\] \*\*Framebuffer Resizing\*\*
> \- \[x\] \*\*Perspective Correct\*\*
> \- \[x\] \*\*Scissor Clipping\*\*
> \- \[x\] \*\*Depth Testing\*\*
> \- \[x\] \*\*Blend Modes\*\*
> \- \[x\] \*\*Face Culling\*\*

---

<div class="post-metadata">

**Author:** ![maple](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/maple/32/12677_2.png) [@maple](https://forum.clockworkpi.com/u/maple)\
**Post date:** [October 23, 2025, 5:11am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/14 "2025-10-23T05:11:17Z")

</div>

doing a framebuffer on PSRAM is not too difficult: [initial PSRAM framebuffer · Lana-chan/picocalc\_lua@03839ca · GitHub](https://github.com/Lana-chan/picocalc_lua/commit/03839caa044d31bd232186cdbb06b848e3938204)

the main issue with my implementation is how rp2040-psram has a 20 byte transfer limit due to how the PIO is set up (i tried modifying it without much success, still need to learn how to work with the PIO) and so writes to it are quite fast (drawing 1000 circles directly to the screen is 5x slower than drawing 1000 circles to PSRAM and then blitting PSRAM to screen) but the bottleneck is in copying the entire PSRAM to the screen. it’s possible you could write a PIO program to do this without having to use the Pico RAM as intermediate at all to speed it up further

---

<div class="post-metadata">

**Author:** ![JackCarterSmith](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/jackcartersmith/32/11509_2.png) [@JackCarterSmith](https://forum.clockworkpi.com/u/JackCarterSmith)\
**Post date:** [October 23, 2025, 9:12am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/15 "2025-10-23T09:12:15Z")

</div>

I see this code use the 2nd core to transfer framebuffer to the screen, and what about using a combination of DMA+PIO instead? I suppose this can avoid using the internal RAM.

CPU =\> PIO/FB =\> DMA =\> SPI

I don’t know if it’s feasible or if the DMA would not be too slow.

---

<div class="post-metadata">

**Author:** ![maple](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/maple/32/12677_2.png) [@maple](https://forum.clockworkpi.com/u/maple)\
**Post date:** [October 23, 2025, 10:55am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/16 "2025-10-23T10:55:20Z")

</div>

that’s essentially what i mention at the end of my post :] i just haven’t gotten that to work. all attempts i did caused a hang and that was before i had my picocalc modded for debugging

---

<div class="post-metadata">

**Author:** ![JackCarterSmith](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/jackcartersmith/32/11509_2.png) [@JackCarterSmith](https://forum.clockworkpi.com/u/JackCarterSmith)\
**Post date:** [October 24, 2025, 8:31am UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/17 "2025-10-24T08:31:41Z")

</div>

It was for confirmation by repeating 😃

I should try it too, I probably lack sufficient motivation. Having the second core and DMA running in sync seem powerful but complex and long to implement.

---

<div class="post-metadata">

**Author:** ![Ben](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.clockworkpi.com/ben/32/11799_2.png) [@Ben](https://forum.clockworkpi.com/u/Ben)\
**Post date:** [October 24, 2025, 1:07pm UTC](https://forum.clockworkpi.com/t/framebuffer-on-psram/16667/18 "2025-10-24T13:07:10Z")

</div>

I haven’t succeeded in using DMA+PIO for the LCD. Maybe we need someone with more expertise to look at it.
