Search › A-Z › P › Psion Series 3
Psion Series 3
An in-browser original Psion Series 3 that boots the authentic EPOC16 (SIBO) v1.91F system ROM. No standalone JavaScript NEC V30 executor exists, so PCjs's pure-JavaScript x86 core (CPUx86) is reused as the V30 — the Series 3's 8086/80186-class CPU — and wired to a from-scratch model of the two-chip ASIC1 + ASIC2 gate-array set: the flat memory decode, the 240×80 one-bit mono LCD, the tick/free-running/watchdog timers, the 8-source interrupt controller and the ASIC2 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 the flat 1 MB memory map, and sets breakpoints and write watchpoints.
The original Psion Series 3 (1991) was the first SIBO clamshell palmtop: a pocket organiser with a proper QWERTY keyboard and a suite of built-in applications — System, Word, Agenda, Data, Time, World, Calc and Sheet — resident in ROM, sharing the NEC V30 processor and EPOC16 operating system across the whole Series 3 family, but built around the older two-chip ASIC1 + ASIC2 set and a smaller 240×80 display.
The V30 core is provided by PCjs's open-source (MIT) pure-JavaScript x86 executor, reused here and wired to a from-scratch ASIC1+ASIC2 machine written for emulators.org.
Runs on: Web browser
Psion Series 3 Online Emulator
Play Psion Series 3 using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Psion Series 3 — EPOC16 (SIBO) | Psion Series 3 | Psion Series 3 | grey | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
The original Series 3's CPU is a NEC V30 — an 8086-compatible part with the 80186 instruction set, clocked at 3.84 MHz. 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 PsionASIC12(romBytes);
m.install(bus, cpu); // flat CTRL memory over 0..0xFFFFF + ASIC1/ASIC2 I/O ports
cpu.chipset = m.chipsetStub(); // so the CPU can pull IRQ vectors 0x78..0x7F
cpu.reset(); // CS:IP = FFFF:0000 -> ROM reset vector JMP C000:0000
Run loop. We drive cpu.stepCPU() ourselves in sub-ticked frames, advancing the ASIC1 timers (4/32 Hz tick, the 512 kHz free-running counter, the 4 Hz watchdog) 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 -> 240x80 canvas
Because the CPU, bus and ASIC1/ASIC2 model 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-classic-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 over a FLAT map. Unlike the Series 3a (whose ASIC9 pages the V30's 1 MB into a 16 MB space), the classic Series 3's ASIC1 maps memory directly: 0x00000–0x3FFFF is the 256 KB RAM, 0x40000–0x7FFFF is open bus, and 0x80000–0xFFFFF is the 512 KB ROM (holding the reset vector EA 00 00 C0 00 = JMP C000:0000). The hex/disasm view reads through PsionASIC12.peek — the same flat map the CPU uses, with no effects — 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 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 ASIC1 memory-write path (PsionASIC12.writeByte) and pause when a watched V30 address is written. Interrupt injection mimics ASIC1's 8-source controller: a chipset stub returns the IDT vector 0x78 + lowest-pending-source, and the ASIC1 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 original Series 3 is the earliest SIBO clamshell, sharing the family processor — a NEC V30 (8086 pins, 80186 instruction set, 3.84 MHz) running EPOC16 / SIBO from ROM — but built around the older two-chip ASIC1 + ASIC2 set rather than the 3a's single ASIC9. Modelled here from MAME's hardware description:
- ASIC1 — system controller. Bus controller, memory decode, LCD controller, the programmable timers and the 8-input interrupt controller. Crucially the memory map is flat (no pager): 256 KB RAM at
0x00000, open bus, then the 512 KB ROM at0x80000–0xFFFFF. ASIC1 also has a write-protection window (A1ProtectionOn/Off/Upper/Lower) that traps out-of-range writes with an address NMI. - ASIC2 — peripheral controller. The system clock, power/standby switching, buzzer, the SIBO eight-channel serial protocol controller (SSD packs), and the keyboard column-scan: the OS writes a column number to
A2Control1and reads the eight rows back onA2External. The Esc/On key sets the on-key status, waking the machine. - LCD. A 240×80 one-bit mono panel (not the 3a's 480×160 three-level grey), scanned from a single-plane framebuffer at RAM
0x0400, drawn only when ASIC1 status bit 5 (LcdEnable) is set; the row stride comes from theA1LcdSizeregister. - Timers & interrupts. A 4/32 Hz tick, a 512 kHz free-running counter and a 4 Hz watchdog feed ASIC1's 8-source controller on IDT vectors
0x78–0x7F; ASIC2 folds into it through EINT3, and door/expansion and watchdog conditions raise the V30 NMI. - 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.
Every part — the V30 executor, the bus, the ASIC1/ASIC2 model — is plain JavaScript, which is what makes the Series 3 a good debugging target: true per-instruction stepping, live registers, and side-effect-free memory over the real flat map.