Skip to content
MJ
← All projects
GhidraReverse engineeringPyVISAPythonComponent repair

Signal generator calibration: reverse engineering & repair

Reverse engineered legacy calibration software for an Agilent E4425B in Ghidra, reimplemented its procedures as open Python/PyVISA scripts, and repaired the sampler board.

Year
2025
Hardware
Agilent E4425B

OutcomeInstrument calibrates from open scripts instead of 1990s Windows software; sampler board brought back to life.

The problem

An Agilent E4425B signal generator is a fine instrument with a fatal flaw: its calibration procedure lives in ancient, vendor-abandoned software that expects a specific Windows era, and some of its calibration routines are effectively unavailable otherwise. The instrument also had a hardware fault on the sampler board — no output, no obvious cause.

Constraints

  • No source. Only a binary and its interface.
  • No documentation of the calibration algorithms beyond what the binary does.
  • The hardware had to be fixed first — you can’t calibrate a broken instrument.

What I did

Repaired the sampler board at component level — traced the fault on the board itself rather than replacing the module, which is the difference between a working instrument and an expensive brick.

Reverse engineered the calibration software in Ghidra, tracing the numeric routines that the binary runs against instrument readings. The core of several of them turned out to be classic numerical methods: binary search to bracket a value, then Newton–Raphson to converge on the calibration constant.

Reimplemented the procedures as open-source Python over PyVISA — a scripted, version-controlled calibration path that runs on a modern machine over GPIB, and that anyone can read and audit.

Trade-offs

  • Reimplement the algorithm, don’t emulate the binary. Rebuilding the maths is more work than an emulator, but the result is readable, testable and maintainable rather than a black box that only works inside a compatibility layer.
  • Trust the maths, verify the instrument. Newton–Raphson depends on a well-behaved function; where the instrument’s response was nonlinear enough to break that assumption, the bracket-then-converge structure in the original binary already implied the answer, so I kept it.

Evidence

Verification was by measurement: the calibrated instrument against a reference, across the frequency range — not by “the script ran”.

What I’d do differently

I would have written unit tests around the numeric routines first. The algorithms are pure functions of measured inputs, so they’re trivially testable — and the first week of debugging was all about trusting code I shouldn’t have had to trust.

Evidence

Calibration sweep driven over GPIB from the reimplemented Python scripts.