Curta
An authored, in-browser model of the Curta Type I, the hand-cranked mechanical pocket calculator designed by Curt Herzstark and first produced in 1948 — a masterpiece of miniature gearing nicknamed "the math grenade". The Curta has no CPU; it is a precision gear machine, and this is a faithful model of the mechanism itself: the eight setting sliders (the number you dial in), the crank (one turn adds the setting into the answer), the liftable, rotatable carriage, and the two counter rings — the 11-digit results counter and the 6-digit turns counter — driven by a single stepped drum with complementary-nine teeth for subtraction.
It plugs into the shared debugger through a new curta decoder that reads the machine's operation tape — one hand action per step (dial a slider, crank to add or subtract, shift the carriage, clear a ring) — with single-operation step, execution breakpoints on the tape, and write watchpoints on the results-counter digits. It boots at rest, all rings zero, with a demo tape loaded that computes 7 × 6 = 42.
Runs on: Web browser
Curta Online Emulator
Play Curta using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Multiply 7 × 6 = 42 | Curta | Curta | open | Open ⛶ | |
| Multiply 12 × 34 = 408 (carriage shift) | Curta | Curta | open | Open ⛶ | |
| Subtract 100 − 37 = 63 (nine's complement) | Curta | Curta | open | Open ⛶ |
Machines emulated
Notes
Embedding
The Curta here is authored from scratch in one small file, curta.js. It is a plain global — Curta.create(canvas) returns a machine object whose whole mechanical state (setting sliders, results and turns counters, carriage) is ordinary JavaScript, so the debugger reaches straight into it with no wasm heap and no hidden loop.
Boot. Create the machine on a <canvas>, load an operation tape (a list of hand actions), and it sits at rest, all rings zero. Then either run your own loop over curta.step() (advance the tape by one action) or drive it live with curta.perform(op) from the keypad:
var curta = Curta.create(canvas);
var OP = Curta.OP;
curta.load([ // 7 × 6 = 42
{op:OP.SET, pos:0, d:7}, // dial the units slider to 7
{op:OP.ADD},{op:OP.ADD},{op:OP.ADD}, // turn the crank ...
{op:OP.ADD},{op:OP.ADD},{op:OP.ADD} // ... six times
]);
(function turn(){
var r = curta.step(); // 'ok' | 'end' — one hand action
curta.render();
if (r !== 'end') requestAnimationFrame(turn);
})();
The machine is plain fields. Everything the debugger needs is live on the object:
| Member | Kind | What it does |
|---|---|---|
curta.step() | method | Advance the operation tape by exactly one action; returns 'ok' or 'end'. The single-step primitive. |
curta.perform(op) | method | Record a live hand action onto the tape and execute it at once — the keypad path. |
curta.setting · curta.result · curta.turns | fields | The three digit rings (setting register, results counter, turns counter), each an array of digits, units first. |
curta.carriage · curta.lifted | fields | The carriage decimal-shift position and the lift flag (lifted = the crank subtracts). |
curta.peek(a) · curta.poke(a,v) | methods | Side-effect-free read / write of the ring memory (setting · results · turns digits) — used by the debugger. |
curta.onWrite(addr,v) | hook | Called on every ring-digit write; the boot uses it to implement watchpoints on the results counter. |
Because the whole mechanism is ordinary JavaScript, breakpoints are a host-side Set of operation indices checked before each step(), and watchpoints are checked inside onWrite — no changes to the core.
Debugger integration
The plug-in (curta-debug.js) describes the machine to the shared debugger, and a new decoder (debugger/src/cpus/curta.js) makes the operation tape readable. The Curta is mechanical — no CPU, no bytes, no opcodes — so this is an unusual but faithful mapping:
- The operation tape is the program. The "disassembly" view decodes one hand action per address:
SET p=d(dial a slider),CRANK +/CRANK −(a crank turn adding or subtracting),CARRIAGE << / >>(shift a decimal place),LIFT/DROP(raise / lower the carriage),CLEARandCLR SET. Anything unrecognised decodes to.op. - Registers are the machine's programmer-visible state: the
SETTINGregister, theRESULTandTURNScounters, theCARRIAGEposition, theLIFTflag and theOPtape index — all read live and written back each refresh. - Single step is one
curta.step()— the tape advances by one action. Breakpoints are host-side checks on the operation index (click an operation in the disassembly gutter); watchpoints fire insideonWritewhen a watched results-counter digit is written by a crank turn. - Like
cpus/analytical.js, the decoder cannot express a structured action through the byte-masked reader the view provides, so it reads the real op off the live core (window.EMU_BOOT.curta.tape) and falls back to a one-byte kind code only when the core is absent.
Architecture
The Curta is a hand-cranked mechanical pocket calculator, designed by Curt Herzstark — much of it while he was imprisoned in the Buchenwald concentration camp — and first produced in 1948. It is a masterpiece of miniature precision engineering, so densely packed with gears that it became a collector's legend, nicknamed "the math grenade" for its shape and its heft.
All of its work is done by turning a crank, feeding a single stepped drum (a Leibniz stepped cylinder). The parts modelled here (Type I):
- The setting register — eight sliders down the body, each dialled 0-9. This is the number you enter; one crank turn runs it once through the drum.
- The crank — one turn adds the setting number into the results counter, with carries rippling up the digits automatically.
- The carriage — the movable top ring carrying the two counters. Rotating it shifts which decimal place the setting is added at (so you multiply and divide by powers of ten); lifting it engages the drum's nine's-complement teeth so the very same crank turn now subtracts — Herzstark's elegant one-drum trick for both directions.
- The results counter (11 digits) shows the running total; the turns counter (6 digits) counts the crank turns at each carriage position, giving the multiplier or the quotient.
- The clearing ring sweeps the results and turns counters back to zero.
How subtraction works. The drum carries, for each setting digit, teeth for the digit and teeth for its nine's complement. With the carriage lifted, a turn adds the nine's complement plus one — the ten's complement — so the counter runs backward with proper borrows, all in gears, no separate mechanism. Multiplication is repeated addition with carriage shifts; division is repeated subtraction. The default tape multiplies 7 × 6 = 42 by cranking a setting of 7 six times.