Atomis Development Blog

jdBasic on the Fruit Jam

You plug an Adafruit Fruit Jam into a monitor and a keyboard and you have a computer. The prompt is on the screen, and the interpreter is the same one that runs on my desktop.

The board

RP2350B, 320 by 240 over DVI at 60 Hz, a USB host port for the keyboard, a TLV320 codec on a headphone jack, five NeoPixels, three buttons, an SD slot and an ESP32-C6 for the network. About 200 KB are free at the prompt, and 8 MB of PSRAM hold the arrays.

What is in the video

The editor with the Commodore maze one-liner. Control R saves and runs it. When a program stops with an error, any key brings you back into the editor on that line.

NET CLOCK joins the network, takes the time from NTP and the weather from Open-Meteo. Five colour schemes, an analog face, the forecast for the week. 19 KB of BASIC.

Pinball. Pop bumpers, drop targets, a spinner, slingshots, a kickback, a charged plunger, tilt, extra ball, a high score in the flash store. The flippers are on the shift keys, the BOOT button on the board is the plunger. The table redraws in a grid of cells, a frame costs about seven milliseconds.

Control C ends a program wherever it is, in a loop, in a SLEEP, while it serves a web page. The prompt comes back with Break at line N.

STELLAR DRIFT, a shooter with a USB pad. Waves, a boss every fifth wave, power-ups. 20 KB of source, 30 KB still free while it runs.

jdBBS, a browser for a markdown board on my server. News, the boards, the lessons, programs you can pull down and run. Forty columns, colour per character cell.

The sound of the games goes out of the headphone jack. The capture only took the picture, so the video is silent apart from the narration.

The prompt

> a = IOTA(10)
> PRINT SUM(a * a)
385
> m = { "name": "fruit jam", "cores": 2 }
> PRINT m{"name"}
fruit jam

Arrays, maps, lambdas, strings, everything the desktop reads. Programs live in a flash store: DIR, SAVE, LOAD, RUN, EDIT, HELP. RECV takes a file off the serial line. AUTORUN names the program that starts at power-on and leaves a window at boot to cancel it.

The Train jdBasic lessons sit on the board in a lessons folder. RUN lessons/hello1 starts the first one.

P-code from the desktop

jdbasic --pcode prog.jdb on the desktop writes the compiled chunk, and RUN prog.jdpb on the board starts it without lexing or parsing. A 4 KB program starts in 0.17 seconds that way, in 2.53 seconds from source. The file carries the names of the builtins it calls, and the board rewrites the call slots against its own registry.

Three boards, one port

The same code runs on a PicoCalc (RP2350, a 320 by 320 panel, its own keyboard, an SD card) and on an ES3C28P (ESP32-S3 with 8 MB PSRAM, a 2.8 inch panel, touch, a codec). src/ is the interpreter and is not touched. embedded/common/ holds the prompt, the editor, the score engine behind PLAY and the web server, compiled into every image. A board supplies how a byte arrives, how big its console is, where the autorun name lives, and the commands only it has.

Getting it

The code is in the jdBasic repo under embedded/. The RP2350 boards build with pico-sdk 2.3.0 (build_pico.sh fruitjam usb), the ESP32-S3 with ESP-IDF 5.5. doc/languages.md has a chapter on the boards.

Next on my bench is an I2C keyboard for the ESP32-S3 board, so that one gets a prompt on its own screen too.

← Back to all posts