No description
  • C 69%
  • NSIS 18.9%
  • Assembly 5.4%
  • DIGITAL Command Language 4.8%
  • Python 0.8%
  • Other 1%
Find a file
Hans Hübner 0068b8e693 console: fix blocking writes and exit hangs
Use non-blocking I/O on the serial port to prevent the console from
becoming unresponsive when the Pico isn't reading CDC data. Use
tcflush + os.close instead of ser.close to avoid tcdrain hang on exit.
Switch to TCSANOW for immediate terminal restore. Remove non-functional
reset-pico command.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 11:17:34 +02:00
bios vdconfig: page navigation, warm boot fix, dspbnch utility 2026-04-13 15:41:27 +02:00
cpm vdconfig: page navigation, warm boot fix, dspbnch utility 2026-04-13 15:41:27 +02:00
doc clean up 2026-04-10 06:06:41 +02:00
firmware firmware: add WRITE_FILE protocol command (opcode 0x19) 2026-04-17 09:17:58 +02:00
lib BIOS conout: drop cursor toggle + shadow font in RAM (~1.9× faster streams) 2026-04-10 12:07:56 +02:00
rom-code Sync byte protocol, timeout recovery, fix hex parser length counter 2026-03-28 18:48:02 +01:00
test-apps Fix PIO handshake: manual flag set, LOAD_BIOS opcode, boot chain 2026-03-16 06:58:54 +01:00
tools console: fix blocking writes and exit hangs 2026-04-17 11:17:34 +02:00
volksforth vdconfig: page navigation, warm boot fix, dspbnch utility 2026-04-13 15:41:27 +02:00
.gitignore vdconfig: page navigation, warm boot fix, dspbnch utility 2026-04-13 15:41:27 +02:00
CLAUDE.md Add SD card hot-swap detection via card-detect switch on GP27 2026-03-30 23:00:04 +02:00
empty-disk.nsi Switch from CamelForth to VolksForth for config tool 2026-04-06 07:48:42 +02:00
exhibit-image.cfg exhibit: museum mode with text and graphical menu 2026-04-13 15:36:40 +02:00
exhibit-text.cfg exhibit: museum mode with text and graphical menu 2026-04-13 15:36:40 +02:00
exhibit.cfg.example exhibit: museum mode with text and graphical menu 2026-04-13 15:36:40 +02:00
HARDWARE.md CP/M support: boot from .nsi disk images on SD card 2026-03-29 23:01:01 +02:00
HEX-LOADING.md docs: document Intel HEX file loading and banked memory protocol 2026-04-14 18:24:03 +02:00
Makefile exhibit: museum mode with text and graphical menu 2026-04-13 15:36:40 +02:00
nsdiagboot-failure.md Revert parity bypass; fix F977 hang via (FFA1) shadow init 2026-04-05 18:28:13 +02:00
parity-test.bas Revert parity bypass; fix F977 hang via (FFA1) shadow init 2026-04-05 18:28:13 +02:00
PLAN.md Add README and correct /out_flag docs (no auto-assert on port 0x40) 2026-03-16 06:59:53 +01:00
README.md Update README: dev binary persists, reset button is NMI 2026-03-16 08:01:17 +01:00
REWIRE.md CP/M support: boot from .nsi disk images on SD card 2026-03-29 23:01:01 +02:00
ROM-FONT.md ROM font information 2026-03-30 22:47:11 +02:00
TEST-CPM.md CP/M support: boot from .nsi disk images on SD card 2026-03-29 23:01:01 +02:00
TEST-PLAN.md Add README and correct /out_flag docs (no auto-assert on port 0x40) 2026-03-16 06:59:53 +01:00
vdconfig.nsi vdconfig: page navigation, warm boot fix, dspbnch utility 2026-04-13 15:41:27 +02:00

VantaDrive

A Raspberry Pi Pico-based floppy disk emulator for the NorthStar Advantage computer. VantaDrive replaces physical floppy drives by serving disk images from Pico flash storage over the NorthStar PIO board's parallel interface.

It also provides a rapid development workflow: edit Z80 code on a host machine, push the binary to the Pico over USB, press the NMI button on the Advantage, and the program is running in seconds.

How It Works

VantaDrive connects a Raspberry Pi Pico W to the NorthStar Advantage via a PIO (Parallel I/O) board installed in slot 2. The PIO board provides two independent 8-bit data buses with hardware handshaking — one for each direction. The Pico dedicates one CPU core entirely to the PIO handshake, ensuring it can keep up with the Z80 at all times.

A custom two-stage boot ROM ("VantaBIOS") replaces the Advantage's original disk I/O. Stage 1 lives in a 2K EPROM and loads stage 2 from the Pico into RAM. Stage 2 then either runs a development binary or boots an operating system from a disk image.

Host (Mac/Linux)            Pico W                      NorthStar Advantage
  |                          |                             |
  +-- USB serial ----------> |                             |
  |   deploy binaries,       | <--- PIO board (slot 2) --> |
  |   manage disk images     |   P1: Pico -> Z80 (8-bit)  |
  |                          |   P2: Z80 -> Pico (8-bit)  |
  |                          |                             |
  |                          +-- Flash: disk images        +-- VantaBIOS stage 1 (EPROM)
  |                          +-- RAM: dev-mode binary      +-- VantaBIOS stage 2 (loaded from Pico)

Two-Stage Boot Process

Stage 1 — EPROM Boot Loader

Stage 1 is a small (~500 byte) program burned into a 2K EPROM that replaces the Advantage's original boot ROM. On power-up or reset, the Z80 begins executing at address 0x0000 where stage 1 resides.

Stage 1 performs these steps:

  1. Initialise hardware — set up the stack, install the NMI handler, and perform the mandatory I/O reset cycle (the Advantage's I/O subsystem is in an indeterminate state at power-on and must be explicitly reset before any I/O board will respond).

  2. Initialise the display — map the display RAM pages and clear the 640x240 monochrome bitmap screen. All status messages are rendered directly to the bitmap display using a built-in 6x7 pixel font.

  3. Detect the PIO board — read the board identification port (0x74) and check for the expected ID byte (0xDB). If no PIO board is found, stage 1 halts with an error message.

  4. Contact the Pico — send a GET_STATUS command to the Pico and wait for a response. Stage 1 retries up to 10 times with 500ms delays, since the Pico may still be starting up when the Advantage is powered on.

  5. Load stage 2 — send a LOAD_PROGRAM command. The Pico responds with a 2-byte length followed by the stage 2 binary. Stage 1 receives the data into RAM at address 0xF000.

  6. Jump to stage 2 — transfer control to 0xF000.

Stage 2 — RAM-Resident BIOS

Stage 2 is not stored in EPROM — it is loaded from the Pico every time the Advantage boots. This means stage 2 can be updated by simply deploying a new binary to the Pico, without touching the EPROM.

Stage 2 occupies 0xF0000xFBFF (up to 3KB) and provides:

  1. Mode detection — sends GET_STATUS to the Pico. The response flags indicate what content is available:

    • Dev mode (flag 0x01): a development binary has been deployed to the Pico via USB. Stage 2 loads it into RAM at 0xC000 and jumps to it.
    • Disk mode (flag 0x02): disk images are available on the Pico. Stage 2 presents a boot menu for image selection and boots the OS.
  2. Dev mode — loads a program from the Pico into 0xC0000xEFFF (up to 12KB) and executes it. The dev binary persists on the Pico across resets, so pressing the NMI button will re-run the same program. To deploy a different binary, use deploy.py on the host and press the NMI button on the Advantage.

  3. Disk mode (planned) — image selection menu, NorthStar OS bootstrap, and a CP/M-compatible BIOS shim at 0xFC00 that translates OS disk I/O calls into VantaDrive protocol commands.

Memory Map When Stage 2 Is Running

Address Range Contents
0x00000x07FF Boot EPROM (stage 1, still mapped)
0x40000x7FFF Display RAM page 8 (columns 063)
0x80000xBFFF Display RAM page 9 (columns 6479)
0xC0000xEFFF User program / OS load area
0xF0000xFBFF Stage 2 code
0xFC000xFFCF BIOS shim jump table (planned)
0xFFD00xFFEF Display state variables
0xFFF00xFFFF Stack

Communication Protocol

Physical Layer

The Pico and the Advantage communicate through the PIO board's two DB-15 connectors, each carrying an independent 8-bit data bus with hardware handshake signals:

  • P1 (lower connector) — Input port, Pico to Z80. The Pico drives 8 data lines (GP0GP7) and pulses /in_strobe (GP16) to latch data. The PIO board sets /in_flag when data is ready. The Z80 polls for /in_flag, reads the byte, and resets the flag. The Pico watches /in_flag (GP17) to confirm the Z80 has read each byte before sending the next.

  • P2 (upper connector) — Output port, Z80 to Pico. The Z80 writes to port 0x40 to latch the data, then accesses port 0x45 to assert /out_flag (the write alone does not signal the Pico). The Pico reads the byte from GP8GP15 and asserts /out_ack (GP19). The PIO board clears /out_flag, and the Z80 sees the acknowledgement in the status register.

All signals are active low. The Pico's 3.3V outputs meet TTL input thresholds, and its GPIO inputs are 5V-tolerant, so no level shifting is needed.

Byte Transfer Timing

Each byte transfer takes approximately 17 microseconds, giving a throughput of about 57 KB/s. A 256-byte disk sector transfers in roughly 4.5 milliseconds.

The Pico runs its PIO handler on a dedicated CPU core (Core 1) to ensure deterministic response times. Core 0 handles USB serial communication, storage management, and the status LED.

Command Protocol

All communication is initiated by the Z80. Each transaction begins with a 4-byte command block sent from the Z80 to the Pico:

Byte Contents
0 Opcode
1 Parameter 1
2 Parameter 2
3 Parameter 3

The Pico responds with a status byte (0x00 = success, 0x80+ = error), optionally followed by a data phase whose format depends on the command.

Commands

GET_STATUS (0x03)

Reports what content is available on the Pico.

  • Parameters: none (all zero)
  • Response: status byte, then a flags byte:
    • Bit 0 (VD_STATUS_DEV_MODE): a dev-mode binary is loaded
    • Bit 1 (VD_STATUS_DISK_MODE): disk images are available

Used by both stage 1 (to verify the Pico is alive) and stage 2 (to decide which mode to enter).

LOAD_PROGRAM (0x04)

Transfers a binary from the Pico to the Z80.

  • Parameters: none (all zero)
  • Response: status byte, then 2-byte length (little-endian), then the program data

Stage 1 uses this to load stage 2 (into 0xF000). Stage 2 uses it to load a dev-mode binary (into 0xC000). The dev binary persists on the Pico and can be served again on subsequent resets.

READ_SECTOR (0x01)

Reads a 256-byte sector from a disk image.

  • Parameters: track (069), sector (09), drive number
  • Response: status byte, then 256 bytes of sector data

Tracks 034 are side 0, tracks 3569 are side 1 (matching the NorthStar .nsi disk image format: 35 tracks x 2 sides x 10 sectors x 256 bytes = 179,200 bytes per image).

WRITE_SECTOR (0x02)

Writes a 256-byte sector to a disk image.

  • Parameters: track (069), sector (09), drive number
  • Response: status byte (ready to receive), then the Z80 sends 256 bytes of data, then the Pico sends a final status byte confirming the write

SET_IMAGE (0x05)

Selects which disk image to mount on a given drive.

  • Parameters: image index, 0, 0
  • Response: status byte

LIST_IMAGES (0x06)

Lists available disk images on the Pico.

  • Parameters: none (all zero)
  • Response: status byte, image count, then image name data

Error Codes

Code Name Meaning
0x00 OK Success
0x81 BAD_OPCODE Unknown command
0x82 BAD_SECTOR Sector number out of range
0x83 BAD_TRACK Track number out of range
0x84 NO_IMAGE No disk image mounted / no binary available
0x85 WRITE_FAIL Write to storage failed
0x86 CRC CRC error

USB Deploy Protocol

Development binaries and disk images are loaded onto the Pico over USB serial from the host machine using tools/deploy.py. The deploy protocol uses a simple framed packet:

[0x56 'V'] [command] [length_lo] [length_hi] [data...] [crc_lo] [crc_hi]

The CRC is CRC-16/CCITT. The Pico responds with ACK (0x06) or NAK (0x15).

Deploy commands:

  • 0x01 — deploy a dev-mode binary (max 16KB)
  • 0x02 — upload a disk image
  • 0x03 — list images
  • 0x04 — delete an image

Usage:

python3 tools/deploy.py program.bin              # deploy dev binary
make deploy BIN=path/to/program.bin              # same, via Makefile

Building

Z80 Code

Requires the pasmo Z80 assembler and memsim2 EPROM emulator tool.

make                    # build all Z80 code (ROMs, BIOS, test apps)
make bios               # build VantaBIOS stage 1 + stage 2
make bios-upload        # upload stage 1 to EPROM emulator
make deploy BIN=app.bin # deploy binary to Pico via USB

Pico Firmware

Requires the Raspberry Pi Pico SDK (PICO_SDK_PATH environment variable).

cd firmware
mkdir -p build && cd build
cmake .. && make

Flash the resulting vantadrive.uf2 by holding BOOTSEL on the Pico, connecting USB, and copying the file to the RPI-RP2 drive that appears.

LED Status

The Pico W onboard LED indicates the current state:

Pattern Meaning
Slow blink (1s period) Waiting for NorthStar power
Brief flash every 2s Connected, idle
Solid on Data transfer in progress

Hardware

See HARDWARE.md for complete wiring tables (Pico GPIO to DB-15 pin mapping) and TEST-PLAN.md for the step-by-step bring-up procedure.