Dit project beschrijft de volledige softwarematige ontleding van de Philips PM5139, een 20 MHz functiegenerator uit 1994. Door middel van EPROM-dumps, disassemblage van de 8051-core en de ontwikkeling van Python- en JavaScript-emulators is de werking van het instrument volledig in kaart gebracht.
Belangrijkste resultaten:
- Documentatie: Er is uitgebreide documentatie gemaakt over het signaalpad, de hardware-architectuur (zoals de C-bus en I²C) en de statusbits.
- Ontdekkingen: De analyse onthulde onder andere dat het apparaat slechts zes willekeurige golfvormslots heeft in plaats van de beloofde 24, en dat bepaalde waveforms in de originele ROM ruis bevatten omdat ze analoog gesampled waren.
- Firmware V2.0: Er is een nieuwe firmwareversie ontwikkeld die fabricagefouten herstelt, ruis uit golfvormen verwijdert en nieuwe, berekende waveforms toevoegt.
- Simulator: Er is een browser-simulator gebouwd die de originele firmware instructie voor instructie uitvoert.
Het project combineert statische analyse met dynamische testen in een emulator om de exacte formules voor frequentie, amplitude en offset te verifiëren, wat resulteerde in een volledige set aan technische referenties voor een apparaat waarvoor geen officiële servicehandleiding beschikbaar was.
Philips PM5139 — Reverse Engineering van de Firmware
Het eindresultaat is firmware V2.0, die een fout herstelt die Philips heeft gefabriceerd, zes eigen willekeurige golfvormen (arbitrary waveforms) en een browser-simulator die de originele ROM instructie voor instructie uitvoert.
Wat dit project is
De Philips PM5139 is het topmodel van een familie van drie instrumenten (PM5136 / PM5138A / PM5139). Intern bevat het apparaat een PCB80C652 (een 8051-core met hardware I²C), een 27512 programmageheugen (EPROM) en zes analoge modules die verbonden zijn via een seriële bus.
Er is geen servicehandleiding beschikbaar voor de PM5139; gebruikers zoeken hier in fora al sinds 2010 naar. Wel bestaat er een handleiding voor de PM5138A, het zustermodel van 10 MHz, dat intern bijna identiek is.
Dit project is daarom vanaf de andere kant begonnen: de EPROM dumpen en uitzoeken wat de code doet, totdat het instrument voldoende begrepen werd om het aan te passen. Er waren twee firmwareversies beschikbaar, V1.3 en V1.5, beide 64 KiB M27512 dumps.
Resultaten in één oogopslag
- Disassemblage: Voltooid voor beide versies, circa 23.000 regels, inclusief kruisverwijzingen.
- Geannoteerde listing: 147 benoemde routines, 145 header-commentaren, 3.826 geannoteerde regels.
- Documentatie: 35 secties, 4.600 regels, waarbij elke claim is onderbouwd.
- Signaalpad: Frequentie, amplitude, offset, AM, FM, burst, symmetrie en sweep zijn allemaal berekend en geverifieerd tegen de originele code.
- Hardware: Alle 10 strobes, de C-bus, I²C met alle deelnemers, poorten, toetsenbord, draaiknop en display-bitmap.
- Statusbits: 75 van de 128 bits hebben een gedocumenteerd effect.
- Versie-verschillen: V1.3 en V1.5 zijn structureel voor 91,4% identiek; elke wijziging is benoemd.
- Emulators: Eén in Python, één in JavaScript (circa 8 miljoen instructies per seconde), plus een browser-simulator in één enkel bestand.
- Eigen firmware: V2.0 — een fabricagefout hersteld, checksum afgehandeld, geverifieerd in de emulator en op echte hardware.
Het instrument
| Positie | Type | Functie |
| D301 | PCB80C652 | 8051 core met hardware I²C, 12 MHz |
| D306 | 27512 | Programma EPROM — V1.3 beslaat 0000h–AC70h |
| D310 | X28C64 | Willekeurige (arbitrary) EEPROM op de MOVX bus |
| D305 | PCF8570 | 256 bytes batterij-gebufferde NVRAM op I²C (A0h) |
| D304-A | PCF8576 | LCD-driver op I²C (70h), 20-byte buffer |
| D302-A | SAA3007 | Toetsenbord-encoder, pulsbreedte-gecodeerd op één lijn |
| D307 | 74HCT4514 | Strobe-decoder — het strobe-nummer is adresbit A8…A11 |
De analoge zijde is een seriële C-bus: de UART van de 8051 draait in shift-register modus, waarbij TXD de klok is en RXD de data. Een strobe bepaalt welk van de tien shift-registers de bytes vastlegt. De instructie MOV DPH,#8nh gevolgd door MOVX @DPTR,A activeert strobe $n$. Deze lijn is de sleutel tot de gehele analoge sectie.
De methode: de emulator als meetinstrument
Het lezen van een 44 KB 8051-binair bestand met het blote oog brengt je slechts een derde van de weg. Alles daarna kwam voort uit het uitvoeren van de originele code en het observeren van de output.
Voorbeeld: Om uit te zoeken welke formule de ingevoerde amplitude omzet in de byte op de bus, werd de routine niet gelezen, maar aangeroepen:
c = CPU(rom)
for w in test_values:
set_amplitude(c, w)
c.call(0x0AAC) # de originele routine, ongewijzigd
print(w, c.ram[0x1C]) # de byte die naar buiten gaat op STR9
Door de input te variëren en de output te lezen, kon dit worden gecontroleerd tegen een hypothese. Dit werkte voor frequentie, amplitude, offset, AM-diepte, FM-deviatie, burst-count, symmetrie en beide sweep-karakteristieken.
Verfijningen in de methode:
- Kijk naar de bus, niet naar het display: Veel statusbits sturen niet het display aan, maar de analoge modules. Deze zijn alleen zichtbaar als telegrammen op de C-bus. Door
MOV SBUF,… en de afsluitende MOVX @DPTR te registreren, steeg het aantal gedocumenteerde bits van 54 naar 75.
- Druk op toetsen, pas niet handmatig de RAM aan: Het handmatig instellen van een RAM-byte kan staten produceren die het instrument nooit in werkelijkheid aanneemt. Door echte toetsencodes via de geëmuleerde SAA3007 te injecteren, werden staten bereikt die de firmware daadwerkelijk gebruikt.
- Twijfel eerst aan de emulator: Drie bugs in de core produceerden "onverklaarbaar" gedrag van de firmware:
ACALL werd uitgevoerd als AJMP, een ontbrekende auxiliary-carry flag (waardoor DA A fouten gaf) en een dubbele toetsenbord-interrupt.
De weg hiernaartoe
- Statisch: Een disassembler met een volledige opcode-tabel, gevolgd door recursive descent met jump-table heuristieken. Dit produceerde 30.508 bytes aan code.
- Dynamisch: Een trace-run van 86 miljoen cycli (koude start, alle 23 frontpaneeltoetsen, draaiknop in beide richtingen, elke modus). Dit identificeerde precies één gebied dat de statische analyse had gemist.
- Schema's: De OCR van de servicehandleiding was onbruikbaar voor schema's, maar de afbeeldingen op 400 dpi waren uitstekend. Een script (
lines.py) werd gebruikt om lijnsegmenten uit de bitmap te extraheren waar visuele inspectie te onnauwkeurig was.
- Chips uitlezen: Een 27C64 gelabeld "SINUS 1.1" en een X28C64 werden uitgelezen en hun inhoud gedecodeerd.
- Versie-verschillen: Door beide ROM's te tokeniseren (relatieve jump-afstanden in plaats van absolute doelen) en
SequenceMatcher te gebruiken, ontstond een adresmapping die overleefde ondanks code-verschuivingen.
De interessante ontdekkingen
Een ruisige golfvorm
De drie ingebouwde willekeurige curves bevinden zich op A047h, A447h en A847h. De derde curve heeft dezelfde vorm als een tabel die al in de ROM staat, maar met 563 richtingsveranderingen tegenover 13, en een standaarddeviatie van 4,1 LSB. Deze was gesampled van een analoge bron in plaats van berekend; het is in feite dezelfde golfvorm maar dan met ruis.
De 30 dB niveauladder
De schone versie van deze tabel bleek een logaritmische niveauladder te zijn (een amplitude- of attenuatietestpatroon). De 1024 punten zijn verdeeld in tien sinusbogen met een ratio van $0,681 = 10^{(-1/6)}$, wat neerkomt op 3,33 dB per stap en 30,1 dB in totaal.
STR9 verzendt 16 bits als twee 1-byte telegrammen
De amplitude-controller heeft twee shift-registers op één strobe, maar de firmware verzendt slechts één byte per telegram. De telegrammen komen in paren, circa 42.000 cycli uit elkaar. De eerste byte wordt doorgevoerd naar het tweede register.
De attenuator is geen berekening
Vijf bits in het STR9-telegram sturen relais direct aan: S1 schakelt het DC-generatorbereik, S2…S5 de attenuator-relais. Er zijn geen drempelwaarden om te berekenen; dit staat direct in het schema.
Een verborgen handler
In de jump-table op 0301h landt entry 15 op 031Fh. Daar staat, in plaats van de gebruikelijke AJMP, de handler zelf inline, om een sprong te besparen. Omdat geen enkele jump-instructie in de ROM hiernaartoe wijst, werd dit door statische analyse gemist. Het is de DIAL LOCK handler.
Zes slots, niet vierentwintig
Hoewel het datasheet 24 golfvormgeheugens belooft, zegt de directory in de EEPROM er zes. De berekening bevestigt dit: $1024 \text{ punten} \times 10 \text{ bit}$, gepakt als 4 waarden per 5 bytes $\rightarrow 1280 \text{ bytes per curve}$. $6 \times 1280 = 7680 \text{ bytes}$, wat precies past in de X28C64 (8 KB) chip die daadwerkelijk is gebruikt.
Dode code voor niet-bestaande apparatuur
186 bytes op 9AFFh voeren I²C-verkeer uit met adres 5Ah, een adres dat nergens anders voorkomt. Het lijkt op een fabrieksdiagnose voor een apparaat dat nooit is uitgebracht.
Geen code-executie vanuit de arbitrary EEPROM
Het is onmogelijk om code in een willekeurige golfvorm-slot te plaatsen en deze aan te roepen. De 8051 is een Harvard-architectuur: instructies komen via /PSEN uit de programma-EPROM, data via /RD uit de arbitrary EEPROM. De fysieke verbinding ontbreekt simpelweg.
De frequentie-codering
De display-cijferrij bevindt zich in 3Eh–43h van het beeld dat naar de PCF8576 wordt gestuurd. De formule is: $f = M \cdot 10^{(D-8)} \text{ kHz}$.
Firmware V2.0 — Wat is er nieuw
Firmware V2.0 is gebouwd vanuit V1.5 (of V1.3) met het script mkv20.py.
- Arbitrary curve 3: Vervangen door de schone berekende tabel (ruis verwijderd).
- Arbitrary curve 2: Vervangen door een logaritmische chirp (1 → 40 perioden), omdat de originele curve redundant was.
- Versie-identificatie:
*IDN? geeft nu PHILIPS,PM5139,0,V2.0/0000 terug.
- Display: De reset-sequentie schrijft nu "2.0" in de display-cellen.
- Checksum: Opnieuw berekend en opgeslagen waar de firmware dit verwacht.
Het paasei: muziek en polyfonie
Omdat er 19.509 ongebruikte bytes achter de checksum in V1.5 zitten, kan het instrument muziek spelen via zijn eigen output. De trigger is een onbereikbare achtste entry in de jump-table van het diagnosemenu (vasthouden van LOCAL tijdens het inschakelen).
Polyfonie
Het bleek dat de PM5139 een 1024-punts wavetable DDS is. De TWS is een fase-accumulator die leesadressen genereert voor een snel RAM op unit 4. Omdat een tabel een som van harmonieken kan bevatten, kan het instrument akkoorden spelen. Dit is geen arpeggio, maar meerdere tonen die tegelijkertijd klinken op volle 20 Vpp.
Dit werkt architectonisch als een PPG Wave: een teller die door een single-cycle waveform loopt, direct naar een DAC.
Zes eigen willekeurige golfvormen
Het bestand D310imageV20.bin vult elk slot in de EEPROM:
| Slot | Golfvorm | Vpp | Doel |
| 1 | sinc, 8 loben | 12.17 | Bandbegrenzing, overshoot |
| 2 | ringing, Q≈6 | 17.81 | Settling behaviour |
| 3 | ECG | 12.80 | Demo |
| 4 | staircase, 16 stappen bipolair | 20.00 | Lineariteit, resolutie |
| 5 | gelijkgerichte sinus | 10.00 | Zoals origineel, maar berekend |
| 6 | multi-tone, 5 tonen | 20.00 | Intermodulatie |
De browser-simulator
PM5139_Simulator.html is een zelfstandig bestand waarin de originele V1.3 firmware boot. De 8051-core draait de echte code; timers, interrupts, de C-bus en I²C zijn geëmuleerd. Het display wordt gedecodeerd uit de werkelijke PCF8576-datastroom.
Repository structuur
Documentatie
PM5139HardwareReference.md: Hoofddocument met 35 secties.
PM5139FirmwareModification.md: Instructies voor het wijzigen en flashen van firmware.
PM5139_Tables.md: Commando- en berichtentabellen.
PM5139ChangelogV13_V15.md: Beschrijving van wijzigingen tussen V1.3 en V1.5.
PM5139BitCrossreference.md: Status van flags 20h–2Fh.
HANDOVER.md & BACKLOG.md: Huidige stand van zaken en openstaande vragen.
Firmware en Data
M27512PM5139V13.bin & V15.bin: Originele dumps.
M27512PM5139V20.bin: De aangepaste versie.
D310imageV20.bin: Eigen golfvormen voor de EEPROM.
PM5139V13annotated.asm & V15: Geannoteerde listings.
Tooling
- Emulatie:
emu.py, system.py, core.js.
- Analyse:
mcs51.py, analyze2.py, seqdiff.py.
- Bouwen:
romfix.py, mkv20.py, mkarb.py, mkdoom.py.
Het flashen van de firmware
Waarschuwing: Bewaar altijd de originele EPROM. Alles is alleen omkeerbaar als je de originele chip nog hebt.
De firmware controleert bij het opstarten een byte-som over het bezette bereik. Als deze onjuist is, verschijnt Err 1 en boot het instrument niet. romfix.py berekent en voegt de juiste waarde toe.
Checksum-waarden:
- V1.3: Bereik 0000h–AC6Fh, Checksum byte AC70h, Waarde F2h.
- V1.5: Bereik 0000h–B3C9h, Checksum byte B3CAh, Waarde 99h.
Betrouwbaarheid en openstaande punten
Alles wat als "geverifieerd" is gemarkeerd, is bevestigd door de originele routines in de emulator aan te roepen over verschillende sample-punten.
Nog openstaande vragen:
- 36 van de 128 statusbits hebben een stimulus nodig buiten de zes standaard bedrijfsprofielen.
- NVRAM-velden vanaf offset 0Dh.
- Welk willekeurig commando bereikt welk van de 13 sub-blokken in de 8871h regio.
- Of een remote-commando de parameter-bereikcontrole kan omzeilen.
- Hoe de PM5139 20 MHz genereert met dezelfde klok als het 10 MHz-zustermodel.
Bronnen en Licentie
Bronnen:
pm5138Aservicemanual.pdf (Primair hardware-bron).
- Gebruikershandleidingen van de PM5139 en PM5136.
- Datasheets van alle drie de modellen.
Licentie:
- Het reverse engineering werk (documentatie, tools, emulators, annotaties) is onder de MIT-licentie.
- De Philips-firmware (ROM-images, dumps, listings) is eigendom van Philips. Deze zijn opgenomen voor studie, interoperabiliteit, reparatie en documentatie van instrumenten die al decennia niet meer worden ondersteund.
Philips PM5139 — Reverse Engineering van de Firmware
Het eindresultaat is firmware V2.0, die een fout herstelt die Philips heeft gefabriceerd, zes eigen willekeurige golfvormen (arbitrary waveforms) en een browser-simulator die de originele ROM instructie voor instructie uitvoert.
Wat dit project is
De Philips PM5139 is het topmodel van een familie van drie instrumenten (PM5136 / PM5138A / PM5139). Intern bevat het apparaat een PCB80C652 (een 8051-core met hardware I²C), een 27512 programmageheugen (EPROM) en zes analoge modules die verbonden zijn via een seriële bus.
Er is geen servicehandleiding beschikbaar voor de PM5139; gebruikers zoeken hier in fora al sinds 2010 naar. Wel bestaat er een handleiding voor de PM5138A, het zustermodel van 10 MHz, dat intern bijna identiek is.
Dit project is daarom vanaf de andere kant begonnen: de EPROM dumpen en uitzoeken wat de code doet, totdat het instrument voldoende begrepen werd om het aan te passen. Er waren twee firmwareversies beschikbaar, V1.3 en V1.5, beide 64 KiB M27512 dumps.
Resultaten in één oogopslag
- Disassemblage: Voltooid voor beide versies, circa 23.000 regels, inclusief kruisverwijzingen.
- Geannoteerde listing: 147 benoemde routines, 145 header-commentaren, 3.826 geannoteerde regels.
- Documentatie: 35 secties, 4.600 regels, waarbij elke claim is onderbouwd.
- Signaalpad: Frequentie, amplitude, offset, AM, FM, burst, symmetrie en sweep zijn allemaal berekend en geverifieerd tegen de originele code.
- Hardware: Alle 10 strobes, de C-bus, I²C met alle deelnemers, poorten, toetsenbord, draaiknop en display-bitmap.
- Statusbits: 75 van de 128 bits hebben een gedocumenteerd effect.
- Versie-verschillen: V1.3 en V1.5 zijn structureel voor 91,4% identiek; elke wijziging is benoemd.
- Emulators: Eén in Python, één in JavaScript (circa 8 miljoen instructies per seconde), plus een browser-simulator in één enkel bestand.
- Eigen firmware: V2.0 — een fabricagefout hersteld, checksum afgehandeld, geverifieerd in de emulator en op echte hardware.
Het instrument
| Positie | Type | Functie |
| D301 | PCB80C652 | 8051 core met hardware I²C, 12 MHz |
| D306 | 27512 | Programma EPROM — V1.3 beslaat 0000h–AC70h |
| D310 | X28C64 | Willekeurige (arbitrary) EEPROM op de MOVX bus |
| D305 | PCF8570 | 256 bytes batterij-gebufferde NVRAM op I²C (A0h) |
| D304-A | PCF8576 | LCD-driver op I²C (70h), 20-byte buffer |
| D302-A | SAA3007 | Toetsenbord-encoder, pulsbreedte-gecodeerd op één lijn |
| D307 | 74HCT4514 | Strobe-decoder — het strobe-nummer is adresbit A8…A11 |
De analoge zijde is een seriële C-bus: de UART van de 8051 draait in shift-register modus, waarbij TXD de klok is en RXD de data. Een strobe bepaalt welk van de tien shift-registers de bytes vastlegt. De instructie MOV DPH,#8nh gevolgd door MOVX @DPTR,A activeert strobe $n$. Deze lijn is de sleutel tot de gehele analoge sectie.
De methode: de emulator als meetinstrument
Het lezen van een 44 KB 8051-binair bestand met het blote oog brengt je slechts een derde van de weg. Alles daarna kwam voort uit het uitvoeren van de originele code en het observeren van de output.
Voorbeeld: Om uit te zoeken welke formule de ingevoerde amplitude omzet in de byte op de bus, werd de routine niet gelezen, maar aangeroepen:
c = CPU(rom)
for w in test_values:
set_amplitude(c, w)
c.call(0x0AAC) # de originele routine, ongewijzigd
print(w, c.ram[0x1C]) # de byte die naar buiten gaat op STR9
Door de input te variëren en de output te lezen, kon dit worden gecontroleerd tegen een hypothese. Dit werkte voor frequentie, amplitude, offset, AM-diepte, FM-deviatie, burst-count, symmetrie en beide sweep-karakteristieken.
Verfijningen in de methode:
- Kijk naar de bus, niet naar het display: Veel statusbits sturen niet het display aan, maar de analoge modules. Deze zijn alleen zichtbaar als telegrammen op de C-bus. Door
MOV SBUF,… en de afsluitende MOVX @DPTR te registreren, steeg het aantal gedocumenteerde bits van 54 naar 75.
- Druk op toetsen, pas niet handmatig de RAM aan: Het handmatig instellen van een RAM-byte kan staten produceren die het instrument nooit in werkelijkheid aanneemt. Door echte toetsencodes via de geëmuleerde SAA3007 te injecteren, werden staten bereikt die de firmware daadwerkelijk gebruikt.
- Twijfel eerst aan de emulator: Drie bugs in de core produceerden "onverklaarbaar" gedrag van de firmware:
ACALL werd uitgevoerd als AJMP, een ontbrekende auxiliary-carry flag (waardoor DA A fouten gaf) en een dubbele toetsenbord-interrupt.
De weg hiernaartoe
- Statisch: Een disassembler met een volledige opcode-tabel, gevolgd door recursive descent met jump-table heuristieken. Dit produceerde 30.508 bytes aan code.
- Dynamisch: Een trace-run van 86 miljoen cycli (koude start, alle 23 frontpaneeltoetsen, draaiknop in beide richtingen, elke modus). Dit identificeerde precies één gebied dat de statische analyse had gemist.
- Schema's: De OCR van de servicehandleiding was onbruikbaar voor schema's, maar de afbeeldingen op 400 dpi waren uitstekend. Een script (
lines.py) werd gebruikt om lijnsegmenten uit de bitmap te extraheren waar visuele inspectie te onnauwkeurig was.
- Chips uitlezen: Een 27C64 gelabeld "SINUS 1.1" en een X28C64 werden uitgelezen en hun inhoud gedecodeerd.
- Versie-verschillen: Door beide ROM's te tokeniseren (relatieve jump-afstanden in plaats van absolute doelen) en
SequenceMatcher te gebruiken, ontstond een adresmapping die overleefde ondanks code-verschuivingen.
De interessante ontdekkingen
Een ruisige golfvorm
De drie ingebouwde willekeurige curves bevinden zich op A047h, A447h en A847h. De derde curve heeft dezelfde vorm als een tabel die al in de ROM staat, maar met 563 richtingsveranderingen tegenover 13, en een standaarddeviatie van 4,1 LSB. Deze was gesampled van een analoge bron in plaats van berekend; het is in feite dezelfde golfvorm maar dan met ruis.
De 30 dB niveauladder
De schone versie van deze tabel bleek een logaritmische niveauladder te zijn (een amplitude- of attenuatietestpatroon). De 1024 punten zijn verdeeld in tien sinusbogen met een ratio van $0,681 = 10^{(-1/6)}$, wat neerkomt op 3,33 dB per stap en 30,1 dB in totaal.
STR9 verzendt 16 bits als twee 1-byte telegrammen
De amplitude-controller heeft twee shift-registers op één strobe, maar de firmware verzendt slechts één byte per telegram. De telegrammen komen in paren, circa 42.000 cycli uit elkaar. De eerste byte wordt doorgevoerd naar het tweede register.
De attenuator is geen berekening
Vijf bits in het STR9-telegram sturen relais direct aan: S1 schakelt het DC-generatorbereik, S2…S5 de attenuator-relais. Er zijn geen drempelwaarden om te berekenen; dit staat direct in het schema.
Een verborgen handler
In de jump-table op 0301h landt entry 15 op 031Fh. Daar staat, in plaats van de gebruikelijke AJMP, de handler zelf inline, om een sprong te besparen. Omdat geen enkele jump-instructie in de ROM hiernaartoe wijst, werd dit door statische analyse gemist. Het is de DIAL LOCK handler.
Zes slots, niet vierentwintig
Hoewel het datasheet 24 golfvormgeheugens belooft, zegt de directory in de EEPROM er zes. De berekening bevestigt dit: $1024 \text{ punten} \times 10 \text{ bit}$, gepakt als 4 waarden per 5 bytes $\rightarrow 1280 \text{ bytes per curve}$. $6 \times 1280 = 7680 \text{ bytes}$, wat precies past in de X28C64 (8 KB) chip die daadwerkelijk is gebruikt.
Dode code voor niet-bestaande apparatuur
186 bytes op 9AFFh voeren I²C-verkeer uit met adres 5Ah, een adres dat nergens anders voorkomt. Het lijkt op een fabrieksdiagnose voor een apparaat dat nooit is uitgebracht.
Geen code-executie vanuit de arbitrary EEPROM
Het is onmogelijk om code in een willekeurige golfvorm-slot te plaatsen en deze aan te roepen. De 8051 is een Harvard-architectuur: instructies komen via /PSEN uit de programma-EPROM, data via /RD uit de arbitrary EEPROM. De fysieke verbinding ontbreekt simpelweg.
De frequentie-codering
De display-cijferrij bevindt zich in 3Eh–43h van het beeld dat naar de PCF8576 wordt gestuurd. De formule is: $f = M \cdot 10^{(D-8)} \text{ kHz}$.
Firmware V2.0 — Wat is er nieuw
Firmware V2.0 is gebouwd vanuit V1.5 (of V1.3) met het script mkv20.py.
- Arbitrary curve 3: Vervangen door de schone berekende tabel (ruis verwijderd).
- Arbitrary curve 2: Vervangen door een logaritmische chirp (1 → 40 perioden), omdat de originele curve redundant was.
- Versie-identificatie:
*IDN? geeft nu PHILIPS,PM5139,0,V2.0/0000 terug.
- Display: De reset-sequentie schrijft nu "2.0" in de display-cellen.
- Checksum: Opnieuw berekend en opgeslagen waar de firmware dit verwacht.
Het paasei: muziek en polyfonie
Omdat er 19.509 ongebruikte bytes achter de checksum in V1.5 zitten, kan het instrument muziek spelen via zijn eigen output. De trigger is een onbereikbare achtste entry in de jump-table van het diagnosemenu (vasthouden van LOCAL tijdens het inschakelen).
Polyfonie
Het bleek dat de PM5139 een 1024-punts wavetable DDS is. De TWS is een fase-accumulator die leesadressen genereert voor een snel RAM op unit 4. Omdat een tabel een som van harmonieken kan bevatten, kan het instrument akkoorden spelen. Dit is geen arpeggio, maar meerdere tonen die tegelijkertijd klinken op volle 20 Vpp.
Dit werkt architectonisch als een PPG Wave: een teller die door een single-cycle waveform loopt, direct naar een DAC.
Zes eigen willekeurige golfvormen
Het bestand D310imageV20.bin vult elk slot in de EEPROM:
| Slot | Golfvorm | Vpp | Doel |
| 1 | sinc, 8 loben | 12.17 | Bandbegrenzing, overshoot |
| 2 | ringing, Q≈6 | 17.81 | Settling behaviour |
| 3 | ECG | 12.80 | Demo |
| 4 | staircase, 16 stappen bipolair | 20.00 | Lineariteit, resolutie |
| 5 | gelijkgerichte sinus | 10.00 | Zoals origineel, maar berekend |
| 6 | multi-tone, 5 tonen | 20.00 | Intermodulatie |
De browser-simulator
PM5139_Simulator.html is een zelfstandig bestand waarin de originele V1.3 firmware boot. De 8051-core draait de echte code; timers, interrupts, de C-bus en I²C zijn geëmuleerd. Het display wordt gedecodeerd uit de werkelijke PCF8576-datastroom.
Repository structuur
Documentatie
PM5139HardwareReference.md: Hoofddocument met 35 secties.
PM5139FirmwareModification.md: Instructies voor het wijzigen en flashen van firmware.
PM5139_Tables.md: Commando- en berichtentabellen.
PM5139ChangelogV13_V15.md: Beschrijving van wijzigingen tussen V1.3 en V1.5.
PM5139BitCrossreference.md: Status van flags 20h–2Fh.
HANDOVER.md & BACKLOG.md: Huidige stand van zaken en openstaande vragen.
Firmware en Data
M27512PM5139V13.bin & V15.bin: Originele dumps.
M27512PM5139V20.bin: De aangepaste versie.
D310imageV20.bin: Eigen golfvormen voor de EEPROM.
PM5139V13annotated.asm & V15: Geannoteerde listings.
Tooling
- Emulatie:
emu.py, system.py, core.js.
- Analyse:
mcs51.py, analyze2.py, seqdiff.py.
- Bouwen:
romfix.py, mkv20.py, mkarb.py, mkdoom.py.
Het flashen van de firmware
Waarschuwing: Bewaar altijd de originele EPROM. Alles is alleen omkeerbaar als je de originele chip nog hebt.
De firmware controleert bij het opstarten een byte-som over het bezette bereik. Als deze onjuist is, verschijnt Err 1 en boot het instrument niet. romfix.py berekent en voegt de juiste waarde toe.
Checksum-waarden:
- V1.3: Bereik 0000h–AC6Fh, Checksum byte AC70h, Waarde F2h.
- V1.5: Bereik 0000h–B3C9h, Checksum byte B3CAh, Waarde 99h.
Betrouwbaarheid en openstaande punten
Alles wat als "geverifieerd" is gemarkeerd, is bevestigd door de originele routines in de emulator aan te roepen over verschillende sample-punten.
Nog openstaande vragen:
- 36 van de 128 statusbits hebben een stimulus nodig buiten de zes standaard bedrijfsprofielen.
- NVRAM-velden vanaf offset 0Dh.
- Welk willekeurig commando bereikt welk van de 13 sub-blokken in de 8871h regio.
- Of een remote-commando de parameter-bereikcontrole kan omzeilen.
- Hoe de PM5139 20 MHz genereert met dezelfde klok als het 10 MHz-zustermodel.
Bronnen en Licentie
Bronnen:
pm5138Aservicemanual.pdf (Primair hardware-bron).
- Gebruikershandleidingen van de PM5139 en PM5136.
- Datasheets van alle drie de modellen.
Licentie:
- Het reverse engineering werk (documentatie, tools, emulators, annotaties) is onder de MIT-licentie.
- De Philips-firmware (ROM-images, dumps, listings) is eigendom van Philips. Deze zijn opgenomen voor studie, interoperabiliteit, reparatie en documentatie van instrumenten die al decennia niet meer worden ondersteund.