123testing — Esp32 Devkit C V4 simulation

An interactive Esp32 Devkit C V4 circuit simulation you can run free in your browser on Velxio, by alireza-cs94.

Sketch code

// Busicom141PF_Emulator.ino
// True Intel 4004 CPU emulation of the Busicom 141-PF, running on ESP32.
// No physical calculator hardware is driven -- this build uses the Serial
// Monitor as a virtual front panel (keys typed in, "display" printed out).
//
// REQUIRED: a ROM image file. This emulator executes real 4004 machine
// code, but Anthropic's Claude will not fabricate the original 141-PF
// firmware bytes from memory -- that is a specific historical binary, not
// architecture. Get a legitimate dump from a preservation project (see
// README.md), name it "141pf.rom" (up to 1280 bytes: 4 or 5 x 256-byte
// 4001 pages), and upload it to the ESP32's LittleFS filesystem with the
// Arduino "ESP32 Sketch Data Upload" tool (put it in a /data folder next
// to this .ino) -- or just drop any other 4004 binary in to test the CPU
// core itself (see /rom_selftest for a tiny bundled diagnostic program).
//
// Board: any ESP32 dev board. No external wiring needed for this mode.

#include <LittleFS.h>
#include "Intel4004.h"
#include "Busicom141PF.h"

Busicom141PF machine;

// ---- tiny built-in self-test program, used if 141pf.rom isn't found ----
// Counts 0..9 into R0, printing each value out ROM-port 1 (WRR) so you can
// see the CPU core, bus, and Serial panel working even with no ROM file.
static const uint8_t selftest[] = {
  0xD0,  // addr0: LDM 0     ; ACC = 0
  0xB0,  // addr1: XCH R0    ; R0 = 0
         // loop (addr 2):
  0xA0,  // addr2: LD R0     ; ACC = R0
  0xE2,  // addr3: WRR       ; output ACC to ROM chip0's I/O port
  0x60,  // addr4: INC R0    ; R0 = R0 + 1
  0x40,
  0x02,  // addr5-6: JUN 0x002  ; jump back to loop
};

unsigned long lastStepMicros = 0;
const unsigned long CYCLE_TIME_US = 11;  // real 4004: 10.8us per 8-clock machine cycle

void printPanel(uint8_t romChip, uint8_t val) {
  Serial.printf("[ROM%u port] = 0x%X   shiftReg=0x%03X  ACC=%X CY=%d PC=0x%03X\n",
                romChip, val, machine.shiftRegister, machine.cpu.ACC, machine.cpu.CY, machine.cpu.PC);
}

void printRAMPort(uint8_t chip, uint8_t val) {
  Serial.printf("[RAM%u port] = 0x%X\n", chip, val);
}

void loadROMFromFS() {
  if (!LittleFS.begin(true)) {
    Serial.println("LittleFS mount failed -- running built-in self-test program instead.");
    machine.loadROM(selftest, sizeof(selftest));
    return;
  }
  File f = LittleFS.open("/141pf.rom", "r");
  if (!f) {
    Serial.println("No /141pf.rom found in LittleFS -- running built-in self-test program instead.");
    Serial.println("(See README.md for how to obtain and upload a real ROM dump.)");
    machine.loadROM(selftest, sizeof(selftest));
    return;
  }
  static uint8_t buf[BUSICOM_ROM_SIZE];
  size_t n = f.read(buf, sizeof(buf));
  f.close();
  machine.loadROM(buf, n);
  Serial.printf("Loaded %u bytes from /141pf.rom\n", (unsigned)n);
}

void setup() {
  Serial.begin(115200);
  delay(300);
  Serial.println("\n=== Busicom 141-PF / Intel 4004 emulator (ESP32) ===");
  machine.begin();
  machine.onROM

More projects by alireza-cs94