# OpenScope 2C53T: A clean-room firmware rewrite that turns a $75 scope into a development project

> OpenScope 2C53T replaces the stock firmware on the FNIRSI 2C53T handheld instrument with a reverse-engineered, GPL-3.0 build. It can cold-boot into a live oscilloscope capture, but it is not yet a usable instrument.

**DavidClawson/OpenScope-2C53T** — Open-source reverse engineering and firmware development for the FNIRSI 2C53T oscilloscope/multimeter/signal generator

- Repository: https://github.com/DavidClawson/OpenScope-2C53T
- Stars: 121 · Forks: 10
- Language: C
- License: GPL-3.0
- Published: 2026-08-26 · Updated: 2026-08-26 · Language: en
- Canonical page: https://hysenlabs.com/projects/davidclawson-openscope-2c53t

## What problem this solves and who it is for

The FNIRSI 2C53T is a $75 handheld device that combines an oscilloscope, multimeter, and signal generator. Its stock firmware is buggy, and the hardware is locked behind a proprietary binary. OpenScope 2C53T is a complete clean-room firmware rewrite, built from reverse engineering the original binary. It exists to give developers and hardware hackers control over a cheap instrument that the manufacturer does not support well. The intended audience is not a technician who needs reliable measurements; it is someone who wants to learn how the device works, who wants to contribute to an open-source project, or who wants to experiment with FPGA configuration and embedded firmware. The README is explicit: flash it to help develop it, to explore the hardware, or because the reverse engineering interests you. If you need a working scope today, stay on stock.

## How the cold-boot capture actually works

The core achievement is that the firmware can cold-boot the device, configure the Gowin GW1N-UV2 FPGA itself, arm the capture engine, and render live waveforms from real ADC data. This happens only in the `guest-coldtrace` build target. The MCU configures the FPGA over SSPI, a bit-banged interface. The status register changes from `0x00039020` to `0x0003F460`, with `DONE_FINAL` set, indicating successful configuration. Then the capture engine is armed, and per-channel readout uses `0x04` and `0x05` commands. The README notes that this is reproducible across power cycles on one physical unit. However, the same bytes sent through the SPI3 peripheral are silently discarded, so the bit-banged SSPI is the only working path. This is a concrete constraint: the hardware has a peripheral that should work but does not, and the project has not yet figured out why. The capture path is also not the default: `make` and `make guest` do not configure the FPGA and will not capture. Only `guest-coldtrace` runs the configuration path.

## Getting it running: commands, build targets, and the option byte

The README gives a specific sequence for seeing live waveforms. From the `firmware` directory, run `make guest-coldtrace`. Then, from the repository root, run `python3 ../scripts/iap_flash.py`. The device must be in upgrade mode, which you enter by holding MENU and tapping Power. This build is a guest image: it links at `0x08007000` and runs under the FNIRSI stock IAP bootloader, not under the project's own HID bootloader. Before that, you need a one-time hardware setup: set a 224KB SRAM option byte. The README does not give the exact command for that, but it is a prerequisite. The `guest-coldtrace` build is scope-only: it holds USART2 dark, which the multimeter uses, so the meter is inactive in that image. There is also a PR that adds a dual-boot switcher, letting you keep stock firmware and switch between the two, but that is not merged yet. The flashing script is for USB-C on macOS and Linux, per the README section title.

## The hard limitations: no timebase, fake measurement badges, and a placeholder baseline

The README is unusually honest about what does not work. The scope captures, but it is not a usable instrument. There is no timebase control. Each hardware sweep is a roughly microsecond, 1024-sample snapshot refreshed about 34 times a second. That means a slow signal, a few Hz, appears as a moving level, and anything above about 15 Hz aliases into nonsense. Vertical calibration is a placeholder: the baseline sits around 55 and the trace clips against the top of the plot. The measurement badges on the scope screen are hardcoded strings, not measurements. They will show `1.00kHz` / `707mV` / `50.0%` no matter what you probe. The README calls it 'a real oscilloscope with a vertical axis and no horizontal knob.' That is a direct quote. The multimeter works, but the low-Ω calibration factor is per-device and currently hardcoded to one bench unit. Absolute readings on your hardware have not been checked by anyone. The project explicitly tells you to use a known-good meter alongside it and not trust it alone for anything that matters.

## Feature maturity stages: a system for tracking what is real

The project uses a five-stage maturity model, from S0 (Written) to S4 (Polished). The last two stages exist because the project has repeatedly shipped a number that was plausible, stable, and wrong. S0 means code and host tests exist but nothing on the device reaches it; it is compiled out or draws from a synthetic source. S1 means it is reachable on the device and fed by real hardware data. S2 means it has been checked on the bench against a known input, with the number and method written up in `docs/experiments/`. S3 means a regression test would catch it breaking. S4 means the UX has been considered. Nothing is at S4 yet. Live capture on CH1 is at S2, reproducible on one unit. CH2 is at S1, with only one usable attenuator tap and a vertical offset reference that has never been programmed. Vertical scale is at S3 for some ranges. This staging is not just a label: it forces contributors to distinguish between code that compiles and code that actually works on hardware. It is a useful model for any firmware project that has been burned by fake numbers.

## Alternatives: stock firmware, other open-source scope projects, and the dual-boot option

The obvious alternative is the stock FNIRSI firmware. It is the only choice if you need a working instrument today, and the README says so. The project also mentions a dual-boot switcher in PR #16, which would let you keep stock and switch between the two rather than choosing. That is not merged yet, but it is the practical path for anyone who wants to experiment without losing a usable scope. For open-source oscilloscope firmware in general, there are other projects like sigrok and various logic analyzer firmware, but those target different hardware and do not apply to the 2C53T's specific FPGA and MCU combination. The closest alternative is to reverse engineer the stock firmware yourself, which is what this project did, but that is a massive effort. The real difference in approach is that OpenScope is a clean-room rewrite, not a patched stock image. That means it does not inherit the stock bugs, but it also means every feature has to be rebuilt from scratch, which is why the maturity stages are so low.

## Maintenance and upgrade cost, and license implications

The project is under GPL-3.0, which means any derivative firmware you distribute must also be GPL-3.0. That is a real consideration for commercial use: if you build a product on this code, you must release your source. The README does not discuss licensing beyond the repository metadata, but the license is clear. Maintenance cost is high. The project has been active since at least April 2026, with releases in April and August. The critical path from April to August was the FPGA configuration problem, which is now solved. But the roadmap still includes folding the capture path into the default `make guest` boot, adding timebase control, fixing vertical calibration, and getting CH2 to work. Each of those is a significant engineering effort. The documentation structure, with `docs/experiments/` and `docs/specs/`, suggests a disciplined approach, but it also means contributors need to read and write those documents. Upgrading from one release to another is not trivial: you must reflash and re-verify, and the README warns that the capture build is validated on only one physical unit. Expect to redo the option byte setup if you change units.

## Conclusion

Adopt OpenScope 2C53T if you are a developer or reverse engineer who wants to explore the FNIRSI 2C53T hardware, contribute to firmware development, or experiment with FPGA configuration over SSPI. Do not use it as your primary measurement instrument: the scope has no timebase control, vertical calibration is a placeholder, and the measurement badges are hardcoded strings. The multimeter is unverified on any unit except the developer's bench device. Before flashing, verify your unit's SRAM option byte (the 224KB setting) and be prepared to restore stock via the IAP bootloader if needed. Check the current feature maturity table in the README to see which parts are still at S0 or S1, and confirm that the specific build target you use is the one that actually captures: only `make guest-coldtrace` configures the FPGA. If you need a working scope today, stay on the stock firmware.

## FAQ

### How do I update the firmware on my FNIRSI 2C53T?

Only one build target captures. Run cd firmware && make guest-coldtrace, then run python3 ../scripts/iap_flash.py from the parent directory, which drives the MENU plus Power upgrade mode, detects the device and flashes. Plain make and make guest do not configure the FPGA and will not capture.

### Can I flash OpenScope 2C53T to a 2C23T or 2C53P?

No, and doing so overwrites that device's factory bootloader, because the boards differ in pin assignments, FPGA transport, application base address and bootloader. For a 2C23T use the separate OpenScope-2C23T project. The AT32's ROM DFU mode is unerasable mask ROM, so recovery is almost always possible.

### Is the OpenScope 2C53T firmware accurate enough to trust?

It is validated on one physical unit. Absolute vertical scale traces to a bench source never checked against a reference, the vertical graticule autoscales by default, CH2 has one usable attenuator tap, and the low-ohm calibration factor is hardcoded to that single device. Uncalibrated ranges display -- rather than a guess.

### What does the guest-coldtrace image do differently from other builds?

It is the only target that runs the FPGA configuration path, so it is the only one that captures. It is a guest image linking at 0x08007000 that runs under the FNIRSI stock IAP bootloader rather than the project's HID bootloader, and it still needs the one-time 224KB SRAM option byte from the first-time hardware setup.

### Which features of the FNIRSI 2C53T firmware work on real hardware today?

Live oscilloscope capture from a cold boot in the guest-coldtrace target, measured volts per division and time per division, and button-driven triggering with AUTO, NORMAL and SINGLE modes, level, edge selection and pre-trigger capture as of v0.4.0. The FFT analyses live data, while math channels and protocol decoders are still fed synthetic input.

### Can I keep the stock firmware alongside OpenScope 2C53T?

Yes. A separate pull request adds a dual-boot switcher so you can keep stock and move between the two rather than choosing one. The stated purpose of installing is development, hardware exploration or interest in the reverse engineering, not replacing a trusted instrument.

## Sources

- [Official README](https://github.com/DavidClawson/OpenScope-2C53T#readme)
- [Project repository](https://github.com/DavidClawson/OpenScope-2C53T)
- [Release notes](https://github.com/DavidClawson/OpenScope-2C53T/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/davidclawson-openscope-2c53t
