
फिलिप्स PM5139 / PM5138A / PM5136 फंक्शन जनरेटर की फर्मवेयर रिवर्स इंजीनियरिंग: मापक यंत्रों के रूप में उपयोग किए जाने वाले 8051 एमुलेटर, प्रलेखित हार्डवेयर के 35 अनुभाग, और एक संशोधित फर्मवेयर V2.0
लगभग 1994 का 20 MHz फंक्शन जनरेटर, सॉफ़्टवेयर में खोला गया: दो EPROM डंप, एक 8051 एमुलेटर जिसे मापक यंत्र की तरह इस्तेमाल किया गया, और 35 दस्तावेज़ीकरण अनुभाग जहाँ हर एक दावे के पीछे कोई लिस्टिंग पता, एमुलेटर माप, या स्कीमैटिक है।
इसके अंत में एक फर्मवेयर V2.0 है जो Philips द्वारा भेजे गए एक दोष को ठीक करता है, हमारे अपने छह मनमाने वेवफ़ॉर्म, और एक ब्राउज़र सिम्युलेटर जो मूल ROM को निर्देश-दर-निर्देश चलाता है।

प्रोग्राम EPROM में हर वेवफ़ॉर्म टेबल, सीधे बाइनरी से प्लॉट की गई। नीचे दाईं ओर वह है जिसने इस परियोजना के सबसे दिलचस्प हिस्से की शुरुआत की।
Philips PM5139 तीन-यंत्र परिवार (PM5136 / PM5138A / PM5139) का 20 MHz टॉप मॉडल है। इसके अंदर एक PCB80C652 — हार्डवेयर I²C वाला 8051 कोर — एक 27512 प्रोग्राम EPROM, और एक सीरियल बस से जुड़ी छह एनालॉग असेंबलियाँ हैं।
PM5139 की कोई सर्विस मैनुअल नहीं है। लोग 2010 से फ़ोरम में इसकी तलाश कर रहे हैं। जो मौजूद है वह PM5138A की मैनुअल है, इसकी 10 MHz बहन मॉडल, जो आंतरिक रूप से लगभग समान है।
तो यह परियोजना दूसरे छोर से शुरू हुई: EPROM डंप करो, और समझो कि कोड क्या करता है जब तक यंत्र इतना समझ न आ जाए कि इसे संशोधित किया जा सके।
दो फर्मवेयर संस्करण उपलब्ध थे, V1.3 और V1.5, दोनों 64 KiB M27512 डंप।
| डिसअसेम्बली | दोनों संस्करणों के लिए पूर्ण, ~23 000 पंक्तियाँ, क्रॉस-रेफ़रेंस के साथ |
| एनोटेटेड लिस्टिंग | 147 नामित रूटीन, 145 हेडर टिप्पणियाँ, 3 826 एनोटेटेड पंक्तियाँ |
| दस्तावेज़ीकरण | 35 अनुभाग, 4 600 पंक्तियाँ, हर दावे का स्रोत |
| सिग्नल पथ | आवृत्ति, आयाम, ऑफ़सेट, AM, FM, बर्स्ट, सिमेट्री, स्वीप — सब मूल कोड के विरुद्ध गणना और सत्यापित |
| हार्डवेयर | सभी 10 स्ट्रोब, C-बस, हर प्रतिभागी के साथ I²C, पोर्ट, कीबोर्ड, रोटरी नॉब, डिस्प्ले बिटमैप |
| स्टेट बिट्स | 128 में से 75 प्रलेखित प्रभाव के साथ |
| संस्करण अंतर | V1.3 बनाम V1.5 संरचनात्मक रूप से 91.4 % समान; हर परिवर्तन का नाम |
| एमुलेटर | एक Python में, एक JavaScript में (~8 M निर्देश/सेकंड), साथ ही एक सिंगल-फ़ाइल ब्राउज़र सिम्युलेटर |
| हमारा अपना फर्मवेयर | V2.0 — एक फ़ैक्टरी दोष ठीक, चेकसम संभाला, एमुलेटर और वास्तविक हार्डवेयर पर सत्यापित |
| स्थान | प्रकार | कार्य |
|---|---|---|
| D301 | PCB80C652 | हार्डवेयर I²C वाला 8051 कोर, 12 MHz |
| D306 | 27512 | प्रोग्राम EPROM — V1.3 0000h–AC70h घेरता है |
| D310 | X28C64 | MOVX बस पर मनमाना EEPROM |
| D305 | PCF8570 | I²C (A0h) पर 256 बाइट बैटरी-बैक्ड NVRAM |
| D304-A | PCF8576 | I²C (70h) पर LCD ड्राइवर, 20-बाइट बफ़र |
| D302-A | SAA3007 | कीबोर्ड एनकोडर, एक ही लाइन पर पल्स-चौड़ाई कोडित |
| D307 | 74HCT4514 | स्ट्रोब डिकोडर — स्ट्रोब संख्या एड्रेस बिट्स A8…A11 है |
एनालॉग पक्ष एक सीरियल C-बस है: 8051 का UART शिफ्ट रजिस्टर मोड में चलता है, TXD क्लॉक है, RXD डेटा, और एक स्ट्रोब तय करता है कि दस शिफ्ट रजिस्टरों में से कौन बाइट्स को लैच करता है। MOV DPH,#8nh के बाद MOVX @DPTR,A स्ट्रोब n को फ़ायर करता है। वह एक पंक्ति पूरे एनालॉग अनुभाग की कुंजी है।
यह वह हिस्सा है जो आपकी अपनी परियोजना के लिए चुराने लायक है।
44 KB की 8051 बाइनरी को आँख से पढ़ने पर आप शायद एक-तिहाई रास्ता तय कर पाएँगे। उसके आगे का सब कुछ मूल कोड चलाकर और देखकर कि क्या निकलता है से आया:```python
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
इनपुट को बदलें, आउटपुट पढ़ें, परिकल्पना के विरुद्ध जाँचें। यह
आवृत्ति, आयाम, ऑफ़सेट, AM गहराई, FM विचलन, बर्स्ट
गणना, सममिति और दोनों स्वीप विशेषताओं के लिए काम कर गया। दस्तावेज़ में प्रत्येक सूत्र
उन नमूना बिंदुओं के साथ आता है जिन पर इसे सत्यापित किया गया था।
तीन परिष्करणों ने इसे वास्तव में उत्पादक बनाया:
**बस को देखें, डिस्प्ले को नहीं।** अनुभाग 15 मापता है कि एक स्टेट बिट
डिस्प्ले बफ़र पर क्या प्रभाव डालता है, और 128 में से 74 बिट्स प्रतीत होता है कि कुछ नहीं करते। लेकिन
उनमें से कई डिस्प्ले को नहीं चलाते, वे *एनालॉग
असेंबली* को चलाते हैं — और वे केवल C-बस पर टेलीग्राम के रूप में दिखाई देते हैं।
`MOV SBUF,…` और समाप्ति करने वाले `MOVX @DPTR` को रिकॉर्ड करने से प्रलेखित बिट्स की संख्या
54 से बढ़कर 75 हो गई।
**कुंजियाँ दबाएँ, RAM को मत छेड़ें।** हाथ से एक RAM बाइट सेट करने से
ऐसी अवस्थाएँ उत्पन्न होती हैं जो उपकरण कभी नहीं लेता। इससे हमें दो गलत निष्कर्ष और
कमांड टेबल में एक क्रैश का खर्च आया। एमुलेटेड SAA3007 के माध्यम से वास्तविक कुंजी कोड इंजेक्ट करने से
ऐसी अवस्थाएँ मिलती हैं जिन तक फ़र्मवेयर वास्तव में पहुँचता है — और यह सभी 256 कुंजी कोड्स पर एक
ब्रूट-फ़ोर्स स्वीप था जिसने यह उजागर किया कि कौन सी कुंजी किस हैंडलर को ट्रिगर करती है।
**पहले अपने ही एमुलेटर पर संदेह करें।** हमारे कोर में तीन बग्स ने
"अकथनीय" फ़र्मवेयर व्यवहार उत्पन्न किया: `ACALL` को `AJMP` के रूप में निष्पादित किया गया, एक अनुपस्थित
सहायक-कैरी फ़्लैग (इसलिए `DA A` ने गलत व्यवहार किया और फ़र्मवेयर बाइनरी में गिनती करता प्रतीत हुआ), और एक दोहरा
कीबोर्ड इंटरप्ट। उस अवधि के प्रत्येक निष्कर्ष को बाद में पुनः मापा गया।
---
## यहाँ तक का रास्ता
**पहले स्टैटिक।** एक पूर्ण ऑपकोड टेबल वाला डिसअसेम्बलर, फिर जंप-टेबल ह्यूरिस्टिक्स के साथ रिकर्सिव
डिसेंट। इसने 30 508 बाइट्स कोड उत्पन्न किया और 13 637 बाइट्स को
अगणित छोड़ दिया।
**फिर डायनामिक।** एक ट्रेस रन — कोल्ड स्टार्ट, सभी 23 फ्रंट पैनल कुंजियाँ, नॉब की दोनों
दिशाएँ, प्रत्येक ऑपरेटिंग मोड, 86 मिलियन साइकल — प्रत्येक उस पते को चिह्नित करते हुए जो वास्तव में निष्पादित हुआ। स्टैटिक विश्लेषण के विरुद्ध रखे जाने पर,
इसने ठीक **एक** ऐसा क्षेत्र खोजा जिसे डिसेंट से चूक गया था, और 10 686 अव्याख्यायित बाइट्स
पाँच ज्ञात टेबल ब्लॉक्स निकले।
**फिर स्कीमैटिक्स।** सर्विस मैनुअल का OCR स्कीमैटिक्स के लिए बेकार है,
लेकिन 400 dpi पर पेज इमेज उत्कृष्ट हैं। ओवरलैपिंग टाइल्स में काटे जाने पर, वे
पिन नंबरों तक पठनीय हैं। इस तरह छह शीट्स पढ़ी गईं — और जहाँ पाँच समानांतर ट्रेस
90 पिक्सल की दूरी पर चलते हैं, वहाँ आँख से देखने के बजाय एक स्क्रिप्ट (`lines.py`) ने
बिटमैप से लाइन सेगमेंट निकाले।
**फिर वे दो चिप्स जो निकाले गए थे।** "SINUS 1.1" लेबल वाला एक 27C64
और एक X28C64 पढ़े गए। दोनों को स्कीमैटिक में रखा गया और उनकी
सामग्री को डिकोड किया गया।
**फिर वर्ज़न डिफ।** दोनों ROMs को टोकनाइज़ करना (पूर्ण लक्ष्यों के बजाय
सापेक्ष जंप दूरियाँ) और उन पर `SequenceMatcher` चलाना
एक पता मैपिंग देता है जो कोड मोशन से बच जाती है — इसी तरह V1.3
प्रतीक V1.5 पर ले जाए जाते हैं।
---
## अच्छे हिस्से
### Philips ने एक शोरयुक्त तरंग भेजी
तीन अंतर्निहित आर्बिट्ररी कर्व्स `A047h`, `A447h` और `A847h` पर स्थित हैं।
तीसरे की आकृति वही है जो पहले से ही ROM में गणना किए गए रूप में मौजूद एक टेबल की है — लेकिन
**13 के मुकाबले 563 दिशा परिवर्तन**, और 4.1 LSB का मानक विचलन।
यह गणना किए जाने के बजाय एक एनालॉग स्रोत से सैंपल किया गया था। विचलन का माध्य
शून्य है, 1024 में से केवल दो बिंदु 10 से अधिक विचलित हैं — यह कोई भिन्न तरंग नहीं है, यह
*वही* तरंग है जिस पर शोर है।
### वह टेबल एक 30 dB लेवल लैडर है