Skip to content

JanFromBelgium/japi-base

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Japi Base — Jan's Pico Projects Base

A well-documented, hackable retro computer built on a Raspberry Pi Pico 2 (RP2350). Japi Base provides all the basic I/O of a small computer — video, keyboard, storage and sound — on a single core and a single PIO block, leaving the second core and the remaining PIOs completely free for your own programs.

The goal is a system that is both educational and genuinely usable: clear code, honest documentation, and no hidden defects.

Status: the hardware platform (VGA, PS/2 keyboard, SD card, audio and a switchable CPU clock) is working and verified on real hardware. A code editor and a BASIC are planned as next steps.

Features

  • VGA output — 1024×768 @ 60 Hz (exact VESA timing). Text mode of 127 columns × 64 rows, 64 colours for both foreground and background, 8×12 pixel font (code page CP437, including box-drawing glyphs).
  • Bitmap graphics — a character-aligned bitmap window overlaid on the text screen. The buffer is capped at ~128 KB: up to 416×312 logical pixels at scale 1, or an almost full-screen 832×624 via 2×2 pixels at scale 2.
  • PS/2 keyboard — flexible driver with pluggable layouts (AZERTY/QWERTY/QWERTZ); the active layout is chosen in config.sys.
  • Storage — a 360 KB LittleFS "flash floppy" (always available) plus an optional micro-SD card when inserted, behind one unified DOS-style file API (A: = flash floppy, C: = SD card). Both file I/O (japi_fopen / japi_fread / …) and directory listing (japi_opendir / japi_readdir) are provided in the same API.
  • Audio — PWM stereo output with a built-in 4-channel wavetable synth (ADSR envelopes, volume/pan); advanced users can fill the sample buffer themselves.
  • Switchable CPU clock — three voltage-tracked speeds, selectable at runtime and persisted in flash: 260 MHz (1.15 V), the default 324 MHz (1.20 V) and an opt-in 390 MHz (1.30 V) up-size. The VGA dot clock stays 65 MHz on every tier so the picture never changes. A board that cannot hold a speed is caught by the watchdog and steps down one tier on its own (390→324, 324→260) — no re-flash and no bricking.
  • Free for your code — Core 0 and the unused PIOs/peripherals are entirely yours; the base I/O engine lives on Core 1 + PIO0.

Demo application

Just want to try it? Grab the prebuilt japi_base.uf2 from the Releases page, hold BOOTSEL while plugging in your Pico 2, and copy the file onto the RP2350 drive that appears. (Or build it yourself — see Building below.)

The bundled firmware (Japi Base Pico 2/demo.c) cycles through, advancing on any key:

  1. Showcase — colour palette, full character set, windows, text colours, runtime font redefinition, bar chart, a scale-1 bitmap drawing the four synth waveforms, and 4-channel stereo music (Tetris theme).
  2. Bouncing balls — flicker-free animation on a solid felt background (832×624 screen pixels, scale 2).
  3. The Starry Night — Van Gogh, Floyd–Steinberg dithered into the 64-colour palette (public domain, Google Art Project).
  4. API quick reference — live keyboard test and code examples.
  5. CPU benchmark — a fixed integer workload timed with a clock-independent timer; press Shift+T / t to up- and down-size the CPU clock and watch the throughput scale across 260 / 324 / 390 MHz while the checksum stays identical (proof the silicon is still computing correctly at speed).

Running on a real VGA monitor. The picture on the monitor is razor-sharp; any blur in these photos is the camera, not the hardware.

Showcase page Showcase: palette, character set, waveform bitmap and 4-channel music.

Bouncing balls

Bouncing balls — flicker-free on a solid felt background. ▶ Full video (14 MB MP4)

The Starry Night The Starry Night, Floyd–Steinberg dithered into the 64-colour palette.

API quick reference API quick reference with a live keyboard test.

Hardware

All Japi Base I/O sits on the left side of the Pico 2 (USB at top); the right side (GP16–GP28) stays completely free for your projects. Build it on a breadboard, flash japi_base.uf2, and you can see and hear the demo. You need a Raspberry Pi Pico 2!

Prototype build on perfboard The prototype on perfboard: Pico 2, VGA DAC, PS/2 level shifter, micro-SD adapter and reset button.

GPIO Function Series resistor
GP0 VGA VSYNC 100 Ω
GP1 VGA HSYNC 100 Ω
GP2 / GP3 Blue LSB / MSB 1 kΩ / 470 Ω
GP4 / GP5 Green LSB / MSB 1 kΩ / 470 Ω
GP6 / GP7 Red LSB / MSB 1 kΩ / 470 Ω
GP8 / GP9 Audio L / R see filter below
GP10–GP13 SD SCK / MOSI / MISO / CS (SPI1)
GP14 / GP15 PS/2 CLK / DATA (via level shifter)
GP16–GP28 free for your code

Schematic

Japi Base schematic The complete Japi Base schematic — VGA, PS/2 (with 5 V / 3.3 V keyboard level select), microSD, stereo audio and a GPIO breakout. Download as PDF.

VGA — weighted-resistor DAC

Two GPIO bits per colour drive a VGA input (75 Ω terminated); sync lines go straight out through a 100 Ω series resistor.

GP7 (Red MSB) ──[470Ω]──┐
GP6 (Red LSB) ──[1kΩ ]──┴──> VGA pin 1  (Red)

GP5 (Grn MSB) ──[470Ω]──┐
GP4 (Grn LSB) ──[1kΩ ]──┴──> VGA pin 2  (Green)

GP3 (Blu MSB) ──[470Ω]──┐
GP2 (Blu LSB) ──[1kΩ ]──┴──> VGA pin 3  (Blue)

GP1 (HSYNC)   ──[100Ω]─────> VGA pin 13 (HSYNC)
GP0 (VSYNC)   ──[100Ω]─────> VGA pin 14 (VSYNC)

Pico GND ──> all VGA ground pins (5,6,7,8,10) + the connector's metal shell

Per-channel voltage into 75 Ω: 00=0.00 V, 01=0.20 V, 10=0.43 V, 11=0.63 V (within the 0.7 V VGA spec) → 64 colours.

Audio — PWM + RC filter (per channel)

GP8 (L) / GP9 (R) ──[1kΩ]──┬──[10µF]──> audio out (to powered speakers)
                            │
                          [3.3nF]
                            │
                           GND

1 kΩ + 3.3 nF low-pass (~48 kHz cutoff) smooths the 40 kHz PWM; the 10 µF capacitor blocks DC. Designed for active (amplified) PC speakers.

PS/2 keyboard — via logic-level shifter

The keyboard runs at 5 V; a bidirectional logic-level shifter sits between it and the Pico (3.3 V side). The open-collector pull-ups are provided on the level-shifter module.

Keyboard 5V side          Level shifter          Pico 3.3V side
  PS/2 CLK   ───────────── HV1 ── LV1 ───────────── GP14
  PS/2 DATA  ───────────── HV2 ── LV2 ───────────── GP15
  +5V ── HV   ,   3.3V ── LV   ,   GND ── GND (common)

Micro-SD — SPI1 (no level shifter)

A micro-SD-to-SD adapter with wires soldered straight to the Pico (the card is 3.3 V native). A 100 nF capacitor decouples the adapter's supply.

GP10 ── SCK      GP11 ── MOSI (DI)      GP12 ── MISO (DO)
GP13 ── CS       3.3V ──┬── VCC         Pico GND ── GND
                       [100nF]
                         │
                        GND

Card-detect is intentionally disabled (a background IRQ would disturb the VGA scanline timing). The SD card is optional — the system boots from the LittleFS flash floppy without it.

Reset button

A momentary button pulls the Pico 2 RUN pin to GND, with a 100 nF capacitor for debounce (the standard Pico reset circuit).

RUN ──┬── [button] ── GND
      │
   [100nF]
      │
     GND

Timing & memory budget

  • CPU at 260 MHz, PIO divider 1:1, 4 ticks/pixel → exact 65 MHz pixel clock for 1024×768@60 Hz.
  • 806 scanlines × 60 Hz ≈ 5374 CPU cycles per scanline for the base engine (rendering + keyboard + audio).
  • Audio: PWM at 40 kHz, sample rate 24 180 Hz (one sample every two scanlines) to keep per-scanline IRQ work bounded.
  • Bitmap buffer cap: 128 KB (JAPI_BITMAP_MAX_RAM). The demo's full-screen Starry Night uses 416×312 = 129 792 bytes at scale 2.
  • The scanline buffers and the whole render path live in RAM, so LittleFS flash writes never disturb the video signal.

Building

Requirements: Raspberry Pi Pico SDK 2.x (PICO_SDK_PATH set), CMake, Ninja, arm-none-eabi-gcc. Third-party libraries (FatFs_SPI, pico-lfs/littlefs) are vendored, so no extra fetching is needed.

cd "Japi Base Pico 2"
mkdir -p build && cd build
cmake -G Ninja ..
ninja

Flash by holding BOOTSEL while plugging in the Pico 2, then:

cp "Japi Base Pico 2/build/japi_base.uf2" /media/<user>/RP2350/

Hello, Japi Base

#include "japi_base.h"

int main(void) {
    japi_init();                                  // clock, VGA, keyboard, SD
    vga_clear(VGA_WHITE, VGA_DARK_BLUE);
    vga_print(2, 4, "Hello from Japi Base!", VGA_YELLOW, VGA_DARK_BLUE);
    japi_play(NOTE_C5, 200);                      // a short beep

    for (;;) {
        vga_wait_vblank();                        // publish writes to the screen
        if (japi_has_char()) {
            uint16_t k = japi_get_char();
            if (k == JAPI_KEY_ESCAPE) break;
        }
    }
    return 0;
}

vga_set_char / vga_print / vga_clear write into a back buffer; the scanline reads from a separate front buffer. vga_wait_vblank() swaps them during the vertical blanking interval, so each frame is shown atomically (no tearing, no half-finished updates), and your render can take longer than a single frame without consequence. The convention is familiar from SDL's SDL_RenderPresent or OpenGL's glSwapBuffers: write freely, then present once per frame.

Switching the CPU clock

The CPU speed is part of the API. japi_set_cpu_clock(mhz) stores the choice and reboots to apply it cleanly (swapping the VGA program so the picture is unchanged); after boot you can read back what the board is actually running:

int mhz = japi_get_cpu_clock_mhz();      // 260, 324 or 390
if (japi_clock_was_reverted())           // the requested tier was unstable here,
    mhz = japi_clock_reverted_from();    // so the watchdog stepped down a tier

japi_set_cpu_clock(390);                 // persist + reboot into the high gear

A board that cannot hold the requested speed is rescued automatically by the watchdog, so japi_set_cpu_clock is always safe to call — the worst case is a brief reboot that lands one tier lower.

Repository layout

Path Contents
Japi Base Pico 2/ The complete Pico 2 firmware (engine + demo)
images/ Screenshots and GIFs used in this README
LICENSE GNU GPL v3
README.md This file
context.md Project conventions and workflow for AI-assisted coding

Firmware files (Japi Base Pico 2/)

File Purpose
japi_base.c / .h / .pio The core engine: VGA output, keyboard input, audio output and file I/O
demo.c / demo.h Demo application (showcase, bouncing balls, Starry Night, API reference, CPU benchmark) and its dithered demo image
third_party_libs.c / .h Third-party libraries needed by the core engine — FatFs (ChaN), SD-over-SPI driver (carlk3), littlefs, pico-lfs — all consolidated, with per-component licence headers and the SD/SPI pin glue at the bottom
font_8x12.h 8×12 bitmap font, CP437 + box-drawing glyphs
japi_kbd_defaults.h Built-in PS/2 keyboard layouts (AZERTY/QWERTY/QWERTZ)
CMakeLists.txt, pico_sdk_import.cmake Build configuration / Pico SDK loader

The previous Pico 1 (RP2040) prototype is archived outside this repository.

Roadmap

  • A keyboard-only code editor (QuickBASIC/Turbo-Pascal look and feel) on Core 0, offering intellisense, split-screen editing, find and replace.
  • Port a BASIC (MMBasic candidate)
  • Integrate my japiZ80 assembler.
  • A Z80 emulator
  • A build/usage manual once the feature set is stable.

Credits

  • FatFs_SPI — SD card over SPI, by carlk3.
  • pico-lfs — LittleFS for RP2040/RP2350, by Timo Kokkonen.
  • littlefs — the littlefs project.
  • The Starry Night (Vincent van Gogh, 1889) — public domain, via Wikimedia Commons / Google Art Project.

License

Released under the GNU General Public License v3 or later — see LICENSE for the full text.

The third-party libraries consolidated into third_party_libs.c keep their original notices (visible in the licence block at the top of that file):

  • FatFs (ChaN) — BSD 1-clause style
  • SD-over-SPI driver (Carl John Kugler III) — Apache 2.0
  • littlefs — BSD-3-Clause
  • pico-lfs (Timo Kokkonen) — GPL-3.0-or-later

The GPL-3 component (pico-lfs) is what makes the combined Japi Base binary GPL-3 as distributed.

About

A well-documented retro computer on the Raspberry Pi Pico 2 (RP2350): VGA 1024x768, PS/2 keyboard, SD + flash storage, stereo synth — one core handles it all, the rest is yours.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors