Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Philips-PM-5139-5138A-5136-Firmware-Project — Firmware reverse engineering of the Philips PM5139 / PM5138A / PM5136 function generators: 8051 emulators used as measuring instruments, 35 sections of documented hardware, and a corrected firmware V2.0 | Kitploit
Tools/GitHubGitHub/doctormord/philips-pm-5139-5138a-5136-firmware-project
Embedded Systems SecurityStatic AnalysisDynamic Analysis (Sandboxing)Reverse EngineeringHardware SecurityBinary AnalysisPapers & ResearchLearning & EducationFirmware Analysis

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
GitHubdoctormord/philips-pm-5139-5138a-5136-firmware-project

Philips-PM-5139-5138A-5136-Firmware-Project

Firmware reverse engineering of the Philips PM5139 / PM5138A / PM5136 function generators: 8051 emulators used as measuring instruments, 35 sections of documented hardware, and a corrected firmware V2.0

View Repository
47421 days agoNot yet reviewed

Philips PM5139 — Firmware Reverse Engineering

A 20 MHz function generator from about 1994, taken apart in software: two EPROM dumps, an 8051 emulator used as a measuring instrument, and 35 sections of documentation where every single claim is backed by a listing address, an emulator measurement, or the schematic.

At the end of it there is a firmware V2.0 that fixes a defect Philips shipped, six arbitrary waveforms of our own, and a browser simulator that runs the original ROM instruction by instruction.

All waveform tables in the V1.3 ROM

Every waveform table in the program EPROM, plotted straight out of the binary. Bottom right is the one that started the most interesting part of this project.


Contents

  • What this is
  • Results at a glance
  • The instrument
  • The method: the emulator is the measuring instrument
  • The road here
  • The good bits
  • Firmware V2.0 — what is new
  • The easter egg
  • And then it turned out to be polyphonic
  • Six arbitrary waveforms of our own
  • The browser simulator
  • Repository layout
  • Using the tools
  • Reproducing everything
  • Flashing it back
  • How reliable is this?
  • Still open
  • Sources

What this is

The Philips PM5139 is the 20 MHz top model of a three-instrument family (PM5136 / PM5138A / PM5139). Inside sits a PCB80C652 — an 8051 core with hardware I²C — a 27512 program EPROM, and six analogue assemblies hanging off a serial bus.

There is no PM5139 service manual. People have been looking for one in forums since 2010. What exists is the manual for the PM5138A, its 10 MHz sister model, which is internally almost identical.

So this project started from the other end: dump the EPROM, and work out what the code does until the instrument is understood well enough to modify it.

Two firmware versions were available, V1.3 and V1.5, both 64 KiB M27512 dumps.


Results at a glance

Disassemblycomplete for both versions, ~23 000 lines, with cross-references
Annotated listing147 named routines, 145 header comments, 3 826 annotated lines
Documentation35 sections, 4 600 lines, every claim sourced
Signal pathfrequency, amplitude, offset, AM, FM, burst, symmetry, sweep — all computed and verified against the original code
Hardwareall 10 strobes, the C-bus, I²C with every participant, ports, keyboard, rotary knob, display bitmap
State bits75 of 128 with a documented effect
Version diffV1.3 vs V1.5 is 91.4 % structurally identical; every change named
Emulatorsone in Python, one in JavaScript (~8 M instructions/s), plus a single-file browser simulator
Our own firmwareV2.0 — a factory defect fixed, checksum handled, verified in the emulator and on real hardware

The instrument

PositionTypeFunction
D301PCB80C6528051 core with hardware I²C, 12 MHz
D30627512program EPROM — V1.3 occupies 0000h–AC70h
D310X28C64arbitrary EEPROM on the MOVX bus
D305PCF8570256 bytes of battery-backed NVRAM on I²C (A0h)
D304-APCF8576LCD driver on I²C (70h), 20-byte buffer
D302-ASAA3007keyboard encoder, pulse-width coded on a single line
D30774HCT4514strobe decoder — the strobe number is address bits A8…A11

The analogue side is a serial C-bus: the 8051's UART runs in shift register mode, TXD is the clock, RXD the data, and a strobe decides which of the ten shift registers latches the bytes. MOV DPH,#8nh followed by MOVX @DPTR,A fires strobe n. That one line is the key to the whole analogue section.


The method: the emulator is the measuring instrument

This is the part worth stealing for your own project.

Reading a 44 KB 8051 binary by eye gets you maybe a third of the way. Everything past that came from running the original code and watching what falls out:

# What formula turns the entered amplitude into the byte on the bus?
# Don't read the routine. Call it.
c = CPU(rom)
for w in test_values:
    set_amplitude(c, w)
    c.call(0x0AAC)          # the original routine, untouched
    print(w, c.ram[0x1C])   # the byte that goes out on STR9

Vary the input, read the output, check it against the hypothesis. That worked for frequency, amplitude, offset, AM depth, FM deviation, burst count, symmetry and both sweep characteristics. Each formula in the documentation comes with the sample points it was verified over.

Three refinements made it actually productive:

Watch the bus, not the display. Section 15 measures what a state bit does to the display buffer, and 74 of 128 bits appear to do nothing. But many of them don't drive the display, they drive the analogue assemblies — and those are only visible as telegrams on the C-bus. Recording MOV SBUF,… and the terminating MOVX @DPTR lifted the count of documented bits from 54 to 75.

Press keys, don't poke RAM. Setting a RAM byte by hand produces states the instrument never takes. That cost us two wrong findings and one crash into the command table. Injecting real key codes through the emulated SAA3007 gives states the firmware actually reaches — and it was a brute-force sweep over all 256 key codes that revealed which key triggers which handler.

Suspect your own emulator first. Three bugs in our core produced "inexplicable" firmware behaviour: ACALL executed as AJMP, a missing auxiliary-carry flag (so DA A misbehaved and the firmware appeared to count in binary), and a doubled keyboard interrupt. Every finding from that period was re-measured afterwards.


The road here

Static first. A disassembler with a full opcode table, then recursive descent with jump-table heuristics. That produced 30 508 bytes of code and left 13 637 bytes unaccounted for.

Then dynamic. A trace run — cold start, all 23 front panel keys, both directions of the knob, every operating mode, 86 million cycles — marking every address that actually executed. Held against the static analysis, it found exactly one area the descent had missed, and 10 686 of the unexplained bytes turned out to be five known table blocks.

Then the schematics. The service manual's OCR is useless for schematics, but the page images at 400 dpi are excellent. Cut into overlapping tiles, they are readable down to pin numbers. Six sheets were read off this way — and where five parallel traces run 90 pixels apart, eyeballing was replaced by a script (lines.py) that extracts the line segments from the bitmap.

Then the two chips that were pulled. A 27C64 labelled "SINUS 1.1" and an X28C64 were read out. Both were placed in the schematic and their contents decoded.

Then the version diff. Tokenising both ROMs (relative jump distances instead of absolute targets) and running SequenceMatcher over them gives an address mapping that survives code motion — that's how the V1.3 symbols get carried onto V1.5.


The good bits

Philips shipped a noisy waveform

The three built-in arbitrary curves live at A047h, A447h and A847h. The third one has the same shape as a table that already sits in the ROM in computed form — but with 563 direction changes against 13, and a standard deviation of 4.1 LSB.

Download Tool