- C 92%
- Makefile 8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| assets | ||
| docs | ||
| reference/button-monitor | ||
| runtime | ||
| src | ||
| usb-root | ||
| vendor | ||
| .gitignore | ||
| Dockerfile.build | ||
| Makefile | ||
| README.md | ||
| SHA256SUMS.txt | ||
| THIRD_PARTY_LICENSES.md | ||
| USB_README.md | ||
Doom for the Siglent SDS1000X-E
This is a standalone, reproducible project for booting Doom directly from an ordinary MBR/FAT32 USB stick on a Siglent SDS1000X-E. The complete path—from stock U-Boot through a USB-root Linux userspace, FPGA/display/button initialization, and Doom—has been confirmed on the physical scope.
Project layout
| Path | Contents |
|---|---|
src/ |
Siglent Doomgeneric framebuffer/input platform |
runtime/ |
Static FAT-root PID 1 and temporary U-Boot environment |
vendor/doomgeneric/doomgeneric/ |
Pinned Doomgeneric engine sources |
assets/ |
Recovered kernel, original DTB, FPGA bitstream, modules, WAD |
docs/ |
Reconstructed architecture, DT source, kernel config, provenance |
reference/button-monitor/ |
Button/encoder investigation tool and capture |
dist/ |
Final directly-extractable USB ZIP |
usb-root/ |
Staging tree used to create the ZIP |
Why the USB itself is the root filesystem
The recovered kernel has CONFIG_BLK_DEV_INITRD disabled. U-Boot can load and
pass a legacy ramdisk, but Linux ignores it. The kernel does have USB storage,
SCSI disk, DOS partition, VFAT, rootwait, and devtmpfs support built in.
The working boot command therefore uses:
root=/dev/sda1 rootfstype=vfat rw rootwait init=/linuxrc
FAT32 cannot represent a conventional Linux root with symlinks and Unix mode
bits, so /linuxrc and Doom are statically linked and the root is deliberately
flat. Devtmpfs supplies device nodes. The recovered kernel modules, runtime
FPGA image, Doom executable, and WAD are ordinary FAT files.
Runtime sequence
- U-Boot reads the kernel, DTB, and environment from FAT32.
- The copied DTB disables the NAND/SMC controller.
- Linux mounts the USB FAT partition as
/and runs/linuxrc. - PID 1 mounts devtmpfs/proc/sysfs/tmpfs and holds GPIO 933 low.
- It writes
fpga.bitto/dev/xdevcfg. - It loads the recovered AXI DMA/CDMA/VDMA and Siglent DMA/VDMA/keyboard modules in the stock order.
- It programs the menu VDMA at
0x43000000, raises GPIOs 933/959, and enables the backlight register at0x40610380. - It reproduces the stock dedicated power-button path on GPIOs 922-924.
- It launches Doom, which renders through
/dev/fb0, reads/dev/siglent_kb, and plays monophonic MUS music through the TTC-driven piezo beeper.
The runtime does not create persistent boot logs. Diagnostics remain visible
on ttyPS0 at 115200-8-N-1.
Build
From this directory:
docker build -t siglent-doom -f Dockerfile.build .
docker run --rm -v "$PWD:/src" siglent-doom
The container rebuilds both static ARM executables, creates usb-root/,
validates the kernel header, DTB, module formats, NAND-disabled status, and PID
1 under QEMU user emulation, then produces:
dist/siglent-sds1000xe-doom-usb.zip
That ZIP is the only final file in dist/. Its contents begin directly with
boot_uImage, linuxrc, doom.wad, and the other USB-root entries—there is no
enclosing project directory. The Doom executable inside it is byte-for-byte
identical to the executable used in the successful physical-scope test.
On PowerShell:
docker run --rm -v "${PWD}:/src" siglent-doom
Deploy
Use a USB stick with an MBR partition table and one FAT32 partition. Remove any
old contents, then extract
dist/siglent-sds1000xe-doom-usb.zip directly to the partition root. The ZIP
contains the required empty dev, proc, sys, and tmp directories.
Insert the stick before power-on. Remove it and power-cycle to return to the stock firmware.
Controls
| Scope control | Doom action |
|---|---|
| Vertical or Horizontal encoder | Move forward/backward |
| Vertical Position or Horizontal Position encoder | Turn left/right |
| Vertical or Horizontal encoder push | Use / menu select |
| Vertical Position or Horizontal Position encoder push | Fire / menu select |
| Soft keys 1–6 | Escape, Enter, fire, use, map, run |
| Math / Ref / Roll / Search | Fire / use / map / run |
| Left / Stop / Right / Display-Persist | Turn left / backward / turn right / forward |
| Run/Stop | Fire |
| Power button | Sync the USB filesystem and power off |
The port accepts -invertmove, -invertturn, -swapencoders, and
-pulsems N. See docs/DOOM_PORT.md for details.
The power key is reported by the separate MSP430 supervisor on GPIO 924, not
as a Siglent keyboard event. Its recovered circuit and shutdown sequence are
documented in docs/POWER_BUTTON.md.
The beeper is a single square-wave voice rather than a PCM audio device. Doom
maps the recovered Zynq TTC0 registers and reduces its MUS scores to one
stable melodic voice. Percussion and sound effects are disabled. The
implementation, limitations, and register-level evidence are documented in
docs/BEEPER_SOUND.md.
Flash safety
usb-root/boot_devicetree.dtb is generated from the recovered DTB with
/amba/memory-controller@e000e000 set to status = "disabled". PID 1 contains
no UBI, MTD, or NAND operation. U-Boot itself necessarily originates from the
scope's internal boot storage before it switches to USB.