SearchA-ZC › COSMAC ELF

COSMAC ELF

1976 Open source · Public domain Online

The Cosmac ELF (Popular Electronics, August 1976) was the archetypal RCA 1802 hobby kit: a bare single board you programmed a byte at a time from a hex keypad, with two 7-segment displays for output. This is an in-browser emulator built from a hand-written RCA CDP1802 (COSMAC) CPU core and an original JavaScript front panel - hex keypad, LOAD / RUN / INPUT controls, the two hex displays and the Q lamp - rendered to a canvas. It plugs into the shared debugger, so you can single-step the 1802, set breakpoints and watchpoints, and read every register (D, DF, P, X, T, Q and the sixteen 16-bit R0-RF) and the 256 bytes of RAM. It boots with a small counter program already loaded so the displays are alive.

About the Cosmac ELF ↗

Visit the official site ↗

Runs on: Web browser

COSMAC ELF Online Emulator

Play COSMAC ELF using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Counter demoCOSMAC ELFCOSMAC ELFopenOpen ⛶

Machines emulated

Chips

Notes

Embedding

The Cosmac ELF here is authored from scratch in one small file, cosmac-elf.js, together with a hand-written RCA 1802 core. It is a plain global - CosmacElf.create(canvas) returns a machine object whose whole state is ordinary JavaScript, so the debugger reaches straight into it with no wasm heap or hidden loop.

Boot. Create the machine on a <canvas>, load the built-in demo (or your own bytes), then run your own loop built on elf.step() (execute exactly one 1802 instruction):

var elf = CosmacElf.create(canvas);
elf.loadDemo();                 // counter program + reset (R0 = PC = 0)
(function loop(){
  for (var i = 0; i < 5000; i++) elf.step();   // one 1802 instruction each
  elf.render();
  requestAnimationFrame(loop);
})();

The machine is plain fields. Everything the debugger needs is live on the object:

MemberKindWhat it does
elf.step()methodFetch/execute exactly one 1802 instruction; returns 'ok' or 'idle' (executed IDL). The single-step primitive.
elf.R · elf.D · elf.DFfieldsThe sixteen 16-bit scratchpad registers R0-RF, the 8-bit accumulator D and the 1-bit data flag DF, read and written live.
elf.P · elf.X · elf.T · elf.QfieldsP selects the PC register, X the data-pointer register; T holds the saved X/P; Q is the output flip-flop (an LED).
elf.peek(a) · elf.poke(a,v)methodsSide-effect-free read / write of memory, used by the debugger's memory views.
elf.onWrite(a,v)hookCalled on every memory write; the boot uses it to implement watchpoints.
elf.kpHex(n) · elf.kpLoad() · elf.kpInput()methodsThe front-panel controls: shift a hex nibble into the switch byte, toggle LOAD mode, and the INPUT strobe.

Because D, the R registers and memory are ordinary JavaScript, breakpoints are a host-side Set of PC values (PC = R[P]) checked before each step(), and watchpoints are checked inside onWrite - no changes to the core.

Debugger integration

The debugger plug-in (cosmac-elf-debug.js) reads the live core each refresh and calls EmuKit.defineMachine. Because the whole machine is plain JavaScript, no core hooks were needed beyond the write hook:

  • CPU decoder. The 1802 is neither a 6502 nor a Z80, so a new disassembler lives at /debugger/src/cpus/1802.js (registered as 1802). The 1802 has a clean 8-bit opcode map - high nibble = operation, low nibble = register - so the table is compact; unknown bytes decode as .byte.
  • Registers. D, DF, P, X, T, Q, IE and the sixteen 16-bit R0-RF are read live each refresh and written back through the set callbacks. “PC” is R[P] - the 1802 keeps the program counter in a scratchpad register chosen by P, so which register is the PC changes as the program runs SEP.
  • Memory. One chip: the ELF's 256 bytes of RAM, disassembled with the 1802 decoder. Reads are side-effect-free.
  • Single step is one step(). Breakpoints compare R[P] against a set before each instruction; write watchpoints wrap poke through onWrite and pause the loop the moment a watched cell is written. Both are host-side, so they cost nothing when the debugger is closed.
  • Input. An on-screen hex keypad (0-F) with LOAD / RUN / INPUT drives the same front-panel methods the physical keyboard does, so the keypad works in the shell fold-up, the debugger Controls window and from the host keyboard.

Architecture

The Cosmac ELF (Popular Electronics, August 1976) was the archetypal RCA 1802 hobby kit: a bare single board you programmed a byte at a time from a hex keypad.

  • RCA CDP1802 (COSMAC) - a static CMOS 8-bit CPU with an unusual register-heavy architecture: sixteen 16-bit scratchpad registers R0-RF, any of which can serve as the program counter or a data pointer. An 8-bit accumulator D, a 1-bit carry DF, and the 4-bit selectors P (which R is the PC) and X (which R is the pointer). SEP / SEX pick those registers; subroutine calls are done by pointing P at a new register.
  • 256 bytes of RAM - the whole memory of the original kit; every byte entered by hand.
  • Two 7-segment hex displays - driven by a two-digit output latch loaded by the OUT 4 instruction, which puts the byte at M(R(X)) onto the output port.
  • Hex keypad + LOAD / RUN / INPUT - in LOAD mode a byte is keyed in and the INPUT strobe deposits it into memory and advances; running, the INP instruction reads the keypad and the INPUT button drives external flag EF4.
  • Q output - a single flip-flop set/reset by SEQ/REQ, wired to an LED (and, on real Elfs, a speaker).

With no program the kit does nothing; this one boots with a small counter already loaded so the displays are alive, and you can single-step the fetch-decode-execute cycle one 1802 instruction at a time.