Search › A-Z › P › Psion Series 3a
Psion Series 3a
An in-browser Psion Series 3a that boots the authentic EPOC16 (SIBO) v3.40F system ROM. No standalone JavaScript NEC V30 executor exists, so PCjs's pure-JavaScript x86 core (CPUx86) is reused as the V30 — the Series 3a's 8086/80186-class CPU — and wired to a from-scratch model of the ASIC9 gate array: the memory pager, the 480×160 three-level mono LCD, six timers, the 8-source interrupt controller and the keyboard scanner. The real ROM passes its power-on self-test, boots the EPOC16 kernel, window server and file server, formats a clean internal RAM disk, and paints the System screen with the app suite, which you can navigate with the arrow keys; because the whole machine is plain JavaScript, the shared debugger single-steps the V30 one true instruction at a time, reads and writes the full register file, inspects memory through the real ASIC9 address pager, and sets breakpoints and write watchpoints.
The Psion Series 3a (1993) was the iconic SIBO clamshell palmtop: a pocket organiser with a proper QWERTY keyboard and a suite of built-in applications — System, Word, Agenda, Data, Time, World and Calc — resident in ROM, sharing the NEC V30 processor and EPOC16 operating system across the whole Series 3 family.
The later 480×160 clamshells are the very same machine — the same ASIC9, the same V30-family CPU and LCD — so the Series 3c (1996) and Series 3mx (1998) are their own standalone emulators that share this machine's code, each loading the scripts, ROM and debugger plug-in from /emulator/psion-series3/src/ and booting its own authentic EPOC16 ROM to the clean System desktop. The 3c boots EPOC16 v5.20F “Oak” and adds an EL backlight and an IrDA / second serial channel over the 3a's ASIC9; the 3mx boots EPOC16 v6.16F “Maple” on a NEC V30MX clocked at 27.68 MHz. The debugger, the on-screen and physical keyboards and the arrow-key desktop navigation work identically across all three.
The V30 core is provided by PCjs's open-source (MIT) pure-JavaScript x86 executor, reused here and wired to a from-scratch ASIC9 machine written for emulators.org.
Runs on: Web browser
Psion Series 3a Online Emulator
Play Psion Series 3a using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Psion Series 3a — EPOC16 (SIBO) | Psion Series 3a | Psion Series 3a | grey | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
The Series 3a's CPU is a NEC V30 — an 8086-compatible part with the 80186 instruction set. No standalone JavaScript V30 executor exists, so we reuse the uncompiled PCjs pcx86 bundle purely for its CPUx86 class (a real x86 executor, not a disassembler) and discard the whole IBM-PC machine around it. A bare CPU is built on a 1 MB bus and handed a tiny cmp stand-in and our Psion machine:
var cpu = new CPUx86({ id:'psion.cpu', model:'80186' }); // V30 ~ 8086 pins + 80186 ISA
var bus = new Busx86({ id:'psion.bus', busWidth:20 }, cpu); // 1 MB V30 address space
cpu.initBus(cmp, bus, cpu, null);
var m = new PsionASIC9(romBytes);
m.install(bus, cpu); // CTRL memory over 0..0xFFFFF + ASIC9 I/O ports
cpu.chipset = m.chipsetStub(); // so the CPU can pull IRQ vectors 0x78..0x7F
cpu.reset(); // CS:IP = FFFF:0000 (V30 real-mode reset)
Run loop. We drive cpu.stepCPU() ourselves in sub-ticked frames, advancing the ASIC9 timers (32 Hz tick, FRC1/FRC2, 1 Hz RTC) and delivering interrupts between bursts:
for (var s = 0; s < SUBTICKS; s++) { cpu.stepCPU(SUB); m.tick(SUB); } // timers -> cpu.intFlags |= INTR
m.render(); // scan RAM 0x0400 -> 480x160 canvas
Because the CPU, bus and ASIC9 are ordinary JavaScript, single-stepping is cpu.stepCPU(0) (exactly one instruction), registers are the core's regEAX… fields and get*/set* accessors, and breakpoints and watchpoints are host-side checks — no change to the CPU core.
Debugger integration
psion-series3-debug.js reads the live machine from window.EMU_BOOT and calls EmuKit.defineMachine with the shared x86 disassembler and the full 8086/V30 register set, reusing the exact CPUx86 hooks that pcjs-debug.js uses (regEAX…regEDI, getCS/getIP/getPS and their setters, regLIP as the linear PC).
Side-effect-free memory through the ASIC9 pager. The V30 sees 1 MB, but ASIC9 maps it into a 16 MB physical space (RAM low, ROM at 0x800000 mirrored, and four paged 64 KB windows selected by I/O 0x28/0x2A). The hex/disasm view reads through PsionASIC9.peek — the same translation the CPU uses, but with no effects (memory has none; the ASIC9 registers live in the separate I/O port space) — so what you see is exactly what the V30 fetches. Two more chips expose the raw physical RAM (to watch the LCD framebuffer at 0x0400) and the system ROM linearly.
function stepInsn(){ cpu.stepCPU(0); } // TRUE single instruction — the payoff of the JS route
Breakpoints are a Set of linear PCs; when any is set the loop steps one instruction at a time and compares cpu.regLIP. Watchpoints wrap the ASIC9 memory-write path (PsionASIC9.writeByte) and pause when a watched V30 address is written. Interrupt injection mimics the real 8-source controller: a chipset stub returns the IDT vector 0x78 + lowest-pending-source, and the ASIC9 timers assert cpu.intFlags |= INTR when an unmasked source is pending — the CPU takes the vector through the guest IVT exactly as hardware would.
Architecture
The Series 3a is one of the SIBO family, all of which share the same processor: a NEC V30 (8086 pins, 80186 instruction set, 7.68 MHz) running EPOC16 / SIBO from ROM. Almost everything else is the ASIC9 gate array, modelled here from the MAME hardware description:
- Memory pager. The V30's 1 MB is translated to a 16 MB physical space:
0x00000–0x5FFFFpasses straight through to RAM; four 64 KB windows at0x60000/0x70000/0x80000/0x90000are paged by the0x28/0x2Apage-select registers;0xA0000–0xFFFFFmaps to0xF00000|addr— the fixed ROM window that holds the reset vector (EA 00 00 A0 00=JMP A000:0000). ROM sits at physical0x800000, mirrored. RAM and ROM are separate spaces chosen by bit0x80000of the CPU byte address, so the0x60000/0x70000windows page RAM banks and the0x80000/0x90000windows page ROM banks. The ASIC also mirrors the fitted RAM across the address space according to the Control register's RAM-device-size field — the aliasing EPOC16 probes to auto-size memory and lay out the internal RAM disk. The four page-select registers are byte-addressable (I/O0x28–0x2B, one byte per window), matching the 16-bit ASIC9 bus — the demand pager writes a single window with a byteOUT. - LCD. A 480×160 three-level (paper / grey / black) mono panel, scanned from a two-plane framebuffer at RAM
0x0400(black plane, then the grey plane at+size), drawn only when Control bit 10 (LcdEnable) is set. - Timers & interrupts. A 32.768 Hz tick, two free-running counters (FRC1/FRC2), a 4 Hz watchdog, a 1 Hz RTC and an 8 kHz sound timer feed an 8-source interrupt controller on IDT vectors
0x78–0x7F, with NMI from the status low nibble. - Keyboard. An 8-column matrix strobed by the ControlExtra register (
0x2C) low nibble and read back on Port AB (0x20); the app hot-keys also assert EINT0 to wake the machine. - V30 CPU. PCjs's 80186 executor supplies the common instruction set, but the NEC V30 adds its own
0x0F-escape instructions (bit-fieldINS/EXT, single-bitTEST1/CLR1/SET1/NOT1, packed-BCDADD4S/SUB4S/CMP4Sand nibbleROL4/ROR4) that Intel never had —psion-v30.jsadds them to the core. EPOC16's window server draws text with theEXT/INSbit-field blitter, so these are essential. - POST. A progress latch at I/O port
0x00steps0x10(ROM test) →0x20(RAM test) →0x30(video RAM) →0xF0(done) — the milestone tracker used to bring this port up. The vendored EPOC16 v3.40F ROM passes POST and runs the SIBO kernel on this core.
Family variants. The Series 3c (1996) and Series 3mx (1998) run this exact machine, so they are now their own standalone emulators that share this code rather than a second build: Psion Series 3c and Psion Series 3mx each load these same scripts, ROMs and debug plug-in from /emulator/psion-series3/src/ and select their model through new PsionASIC9(rom, { model, cpuHz }). The 3c boots the EPOC16 v5.20F “Oak” ROM and adds an EL backlight and an IrDA / second serial channel over the 3a’s ASIC9; those extra registers read back sane values so the ROM’s boot-time probe passes and it reaches the desktop. The 3mx boots the EPOC16 v6.16F “Maple” ROM on a NEC V30MX clocked at 27.68 MHz; that clock sets both the per-frame cycle budget and the timer time-base (so the 32 Hz tick, FRCs and 1 Hz RTC stay real-time). Everything else — the pager, the LCD, the interrupt controller, the keyboard matrix, the V30 0x0F instructions and the whole debugger — is identical across the three.
Every part — the V30 executor, the bus, the ASIC9 — is plain JavaScript, which is what makes the Series 3 family a good debugging target: true per-instruction stepping, live registers, and side-effect-free memory through the real address pager.