Announcement

Collapse
No announcement yet.

Announcement

Collapse
No announcement yet.

Let's make a closely MXT like detector!

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • moodz
    replied
    Originally posted by boilcoil View Post
    Hi moodz,
    I still think that AI wouldn't do that much useful work. What AI wrote to you is true and it generates that, based on statistical data, close enough to the code given to as a model, and not because AI understands the code and processes. My opinion remains the same - if you want to have a correct source file, suitable for porting to another microcontroller, you should open the Datasheet of the PIC16C76 and start changing things line by line. For example, the initial "call 0x71" becomes "call init", and address 0x71 gets the label "init". In the initial initialization procedure "000071 clrf 0xA" becomes "000071 clrf PCLAH" , "000072 bcf 0x6,0x2" becomes "000072 bcf PORTB,2" etc. It's really slow work and requires a lot of time, but if you really need to understandably connect the source code with real processes - I don't see another way.. Moreover, whoever wrote the code, structured it very well and it is easy to read (at least those subprograms that I looked at had only one input and only one output).
    Only when the full source code is restored will it be possible to make a correct guess as to which source module refers to which hardware block and process and what exactly it does.
    This is of course just my opinion and there may be an easier way to accomplish the task, so if you can actually do it entirely with AL you will be my hero. Really, I mean it completely seriously.​
    you are right ... but it also comes down to understanding how the AI works and how we can use that tool ( the AI ) to do alot ( all ? ) of the heavy lifting for us.
    Broadly speaking there is a new technique in programming using AI that I will call "CONTEXT ENGINEERING" ... this has evolved from so called "vibe programming". In CE you give the AI the correct context so it can apply its vast programming "knowledge".
    AI s have no desires or motives, they are just vast probability machines that will give you the ( most probable ) right solution .... if you ask the right question(s) ... this is the context.

    In this case the AI looked at the hexdump and regenerated all the raw machine code.
    It then was told that the code is a metal detector and shown the schematic.
    So it matched code functionality to the pin signals ( LCD, ADC, digital io etc etc )
    Then it was shown the user manual for the MXT ... so the AI had information regarding the use ( ie controls and displays ).
    The AI I use already has a very good knowledge of how VLF detectors work ... so now I told it to extract the obvious stuff like VDI, ground balance.
    Then I told the AI to simulate the code ... with stubs attached to present the correct inputs to the detector loop.

    All of this is context ... its how you present it ( the order of questions and context 0 that will determine your success or not.

    This may be all moot ... I do have a fully commented assembly file here that the AI generated. Its identified all the algorithms, math routines, ground tracking etc and It compiles, runs and all the maths, ground trac, VDI etc works.
    The AI even ported it to the 876 chip ( flash version ) because its pin for pin the same as the MXT orgininal.

    HOWEVER

    If Garrett do own the rights to the MXT firmware then it is a copyrighted work under the law.
    If you publish, distribute, or sell your modified firmware, you are likely creating an unauthorized "derivative work". This frequently violates both the original manufacturer's copyright.
    I dunno if Garrett read this forum ... but putting up a fully reverse engineered copy of the source code would be a copyright infringement IMHO.
    Maybe Carl knows ....

    but I can publish snippets ( for edumacational usage )

    eg :

    Click image for larger version

Name:	image.png
Views:	151
Size:	168.2 KB
ID:	449038​​

    Leave a comment:


  • boilcoil
    replied
    Hi moodz,
    I still think that AI wouldn't do that much useful work. What AI wrote to you is true and it generates that, based on statistical data, close enough to the code given to as a model, and not because AI understands the code and processes. My opinion remains the same - if you want to have a correct source file, suitable for porting to another microcontroller, you should open the Datasheet of the PIC16C76 and start changing things line by line. For example, the initial "call 0x71" becomes "call init", and address 0x71 gets the label "init". In the initial initialization procedure "000071 clrf 0xA" becomes "000071 clrf PCLAH" , "000072 bcf 0x6,0x2" becomes "000072 bcf PORTB,2" etc. It's really slow work and requires a lot of time, but if you really need to understandably connect the source code with real processes - I don't see another way.. Moreover, whoever wrote the code, structured it very well and it is easy to read (at least those subprograms that I looked at had only one input and only one output).
    Only when the full source code is restored will it be possible to make a correct guess as to which source module refers to which hardware block and process and what exactly it does.
    This is of course just my opinion and there may be an easier way to accomplish the task, so if you can actually do it entirely with AL you will be my hero. Really, I mean it completely seriously.​

    Leave a comment:


  • Carl-NC
    replied
    Originally posted by moodz View Post
    Strong evidence it's hand-written assembler, not C.
    Yes, it was.

    Leave a comment:


  • moodz
    replied
    top down reverse engineering ( approx 5 minutes with AI assist ). The inputs are the hex dump and the schematic.
    decoded the bank switching.

    See attached PDF ...

    and on this "originality" subject maybe you should be using the 16F876a chip ( flash version and still in production )

    Here is what the AI said....

    Short answer: yes — and it's about as clean a port as you'll ever get, because the 16F876 is essentially the flash successor to the 16C76. Same 14-bit midrange core, same 28-pin pinout, same 8K×14 program memory and 368 bytes RAM, same Timer0/1/2 + dual CCP + SSP + ADC peripheral set. The disassembled code words transfer essentially unchanged; this is exactly the C-part→F-part migration Microchip designed the F876 for, and the big payoff is that it's flash, so you can reflash during the rebuild instead of burning OTP parts.

    The things that actually need attention are few, and only one is a real trap:

    The config word has to be regenerated. You can't literally burn the C76 image — the config word at 0x2007 is encoded differently and the F876 has options the C76 doesn't (BOR, PWRT, and the LVP bit). Set HS oscillator for the 8 MHz crystal, WDT to match the original (the firmware does clrwdt, so it expects WDT enabled), and code-protect to taste.

    The trap is LVP / RB3. On the 16F876, RB3 doubles as the PGM pin for low-voltage programming, and an erased config defaults LVP enabled, which steals RB3 from you as I/O. The MXT uses RB3 as an input (it's in your TRISB=0x8B, feeding the mode/trac switch network). So you must explicitly program LVP = 0 or that switch input dies. The C76 has no LVP bit, which is why this never came up on the original.

    The ADC is 10-bit instead of 8-bit, but it barely matters here. The internal ADC only reads the control pots (the real signal is the external ADS8320), and as long as you leave the result left-justified (ADFM = 0, which is what ADCON1 = 0x00 already gives you), the top 8 bits land in ADRESH exactly where the existing 8-bit reads expect them. So the pot reads work unchanged; you just gain a spare ADRESL you can ignore. If anything you could later widen those reads to 10-bit for finer pot resolution, but it's optional.

    One thing to verify rather than assume: the F876's MSSP is a superset of the C76's basic SSP, and you're only using SPI master, so it'll work — but the SPI clock polarity/phase is set by CKP (SSPCON) plus CKE/SMP (SSPSTAT), and the original writes SSPCON=0x20 / SSPSTAT=0x40. Those should produce the same SPI mode on the MSSP, but since the ADS8320, LTC1446 and the LCD pod all care about edge timing, it's worth a scope check on first bring-up rather than trusting it blind.

    Everything else — the 13.89 kHz CCP1 PWM, the ~244 Hz Timer0 ISR, the 24-bit math, the whole analog front end — is untouched. The analog board doesn't change at all; this is purely an MCU swap plus a regenerated config word.

    Two practical notes. First, you'll almost certainly be using the 16F876A in practice, not the original 16F876 — the non-A part is long obsolete and had errata the A cleaned up. It's pin- and code-compatible; just a couple of flash/EEPROM write-timing and config specifics differ, none of which affect this design. Second, rather than binary-patching the OTP image, the better move is to reassemble the disassembly against the p16f876a include file — you fix the handful of register-name differences (ADRESL now exists, MSSP naming) once and end up with a maintainable, reflashable source project, which is the whole point of moving to a flash part.

    If you want, I can mark up the init routine (0x88 / 0xA9) with the specific F876A register/config changes side-by-side against the C76 originals, so you've got a concrete porting diff to work from.

    FORENSIC CODE ANALYSIS :

    Strong evidence it's hand-written assembler, not C. Several independent tells line up, and a couple are close to decisive.

    The clearest one is the reset layout. The first four words are doing real work crammed into the gap before the interrupt vector:

    0x0000 call 0x71 ; init
    0x0001 clrf TMR0
    0x0002 bsf INTCON,GIE ; enable interrupts
    0x0003 goto 0x3 ; main loop = spin here forever
    0x0004 ... ; interrupt vector

    A C compiler puts a single goto __startup at 0x0000 and leaves 0x0001–0x0003 as dead space, because its runtime (RAM clear, data init, then main) lives in a relocatable block elsewhere. Hand-packing init-call + TMR0 clear + GIE + the spin loop into exactly those four otherwise-wasted vector-slot words is a classic assembly-programmer trick. The "main loop" is literally goto $ — everything runs in the Timer0 ISR.

    Then the indirect-addressing count: only 1.4% of instructions touch INDF/FSR. That's the big one. C on a PIC16 leans heavily on FSR for stack-relative locals, struct passing and pointer derefs — you'd expect that figure several times higher. 1.4% means the code is almost entirely fixed, direct-addressed global variables, which is how a human writes PIC16 assembler, not how a compiler manages C scope.

    The ISR timing is hand-counted. The 20-NOP run at 0x000A is a deliberate phase pad so the sample lands at a fixed point in the TX cycle, and the movlw 5; addwf TMR0 reload is someone trimming the interrupt period by counted instruction cycles. A compiler never emits twenty bare NOPs for timing — that's a person who knows their Tcy budget.

    The math seals it. The routines at 0x5EA / 0x678 work on hand-chosen scratch registers (0x45–0x4E, 0x20–0x22) with explicit carry/borrow propagation, and they have application logic woven into the arithmetic — e.g. branching on bit 5 of variable 0x36 mid-multiply. That's a bespoke fixed-point routine, not a generic compiler library call. And the arithmetic is 24-bit (3-byte): no mainstream PIC16 C compiler of the 2002 era had a native 24-bit type (HI-TECH and CCS both gave you 8/16/32), so a compiler wouldn't naturally land on three bytes — a human picks 24 bits to fit the dynamic range exactly.

    The one thing that pointed the other way, and why I checked rather than assumed: some byte-copy routines flip the bank select per byte (set RP0, read, clear RP0, store, repeat), which is the kind of redundant banking compilers emit. But at 9.9% overall bank-switch density and only ~47 of those tight flip pairs, it's better explained as a hand-written "copy a banked byte" macro reused a lot than as compiler output — especially against everything else.

    So: hand assembler, almost certainly MPASM, written by someone who counted cycles and laid out RAM by hand. (The "Generated by MPLAB" header on the dump is just the disassembler talking, not the original toolchain.) The only caveat I'd put on it is that I can't fully exclude C-with-heavy-inline-asm — but the near-absence of FSR traffic argues there isn't much compiled C hiding in there at all. If you want, I can confirm by scanning for a compiler runtime signature (a HI-TECH/CCS startup clears RAM and inits globals in a very stereotyped way) — if it's hand asm, that fingerprint won't be there.

    THE BIT THAT DOES THE PHASE ( DISC )

    there's no series-expansion arctan and no CORDIC, but there is a phase routine, and it does arctan the cheap way that small MCUs always did — a divide to form the I/Q ratio, then a 32-entry arctan lookup table. The routine at 0x07A5 lays it out end to end:

    07A5 clrf 0x6D ; clear quotient
    07A6 movf 0x6C,W
    07A7 iorwf 0x6B,W
    07A8 btfsc STATUS,Z
    07A9 return ; guard: denominator ~0 (the I->0 / 90-deg case)
    07AA movlw 0xC0 ... movlw 0x0C -> counter = 12
    07AE movlw 0x10 ; <-- 12-iteration shift-subtract DIVIDE
    07AF subwf 0x6D,F ; forms the ratio in 0x6B:0x6C
    07B0 rlf 0x6C,F
    07B1 rlf 0x6B,F
    ... decfsz counter, loop ...
    07B8 rrf 0x6B (x4); bcf top 3 bits ; reduce ratio to a 5-bit index (0..31)
    07BF call L07C3
    07C3 movlw 0x7; movwf PCLATH; movf 0x6B,W; addwf PCL,F ; computed jump into table
    07C7 <32-entry table> ; retlw the angle

    That table at 0x07C7 reads 0, 5, 19, 28, 34, 39, 43, 46, 49, 52, 54, 56, 58, 60, 62, 64, 65, … 80 — monotonic, rising fast then flattening toward a ceiling. That's the arctan curve: angle vs. ratio, saturating as the ratio grows. So the chain is divide → 5-bit index → arctan LUT → angle, with an explicit divide-by-zero guard up front handling the vertical (I→0, 90°) case. CORDIC is ruled out — none of the tables contain the tell-tale atan(2⁻ⁱ) angle sequence (45, 26.6, 14, 7.1, 3.6…) a CORDIC needs.

    A couple of things fell out of dumping the other tables that also correct an earlier guess of mine. The 100-entry table at 0x1F81 that I'd tentatively called a "VDI/scaling curve" is actually a binary→packed-BCD table (value = BCD of the index: 0→0x00 … 99→0x99) — pure display formatting. And 0x1F08 is a hex→ASCII table (0x30–0x39, 0x41–0x46). Both are for the LCD, not the signal path. The arctan LUT is specifically the 32-entry one at 0x07C7. The remaining odd tables (0x07EE, the descending 0x1F2D) are likely the complementary-octant angle range and/or audio/sensitivity curves — the single 32-entry table only covers one octant, so there's almost certainly quadrant/octant folding (swap I↔Q when the ratio exceeds 1, then reflect) wrapped around it, plus sign handling for the full target-ID range.



    moodz



    Attached Files

    Leave a comment:


  • boilcoil
    replied
    Don't forget that the ROM of the PIC16C76 is only 8k, which, in my opinion, means that the written code is highly optimized (almost certainly in assembler), so the decompiled data of HEX file are as close as possible to the original, but quite different from the list-assembly file, if this program was written in "C". This means that in order to understand what the logic of the processes in the metal detector is, you must first restore the assembler program, in the original form understandable to you (variables - designated only as cells in the decompiled file, subprograms designated only as addresses, etc.). Here AI could not help you, because this concerns not only code, but also expected possible actions controlled by the code.
    Moreover, in order to fit into this small ROM volume, the programmer, writing in assembler, used repeatedly block subprograms for calculations and control, which he used from different places in the main program, and when referring/calling to them, he loaded them with different input values, which makes things even more complicated.
    My opinion is that the extracted HEX file is a great achievement and is ready for the construction of a metal detector, the circuit and hardware of which are known, but it is an extremely difficult task to generate an understandable source file by compiling.
    I would like to repeat again that in this case AI is unlikely to be useful.​

    Leave a comment:


  • Taktyk
    replied
    Originally posted by KRinAZ View Post
    A quick update -

    I'm going to take a shot at assembling code to program a PIC16F76 and test the functionality. Seems like that would be a good step towards creating code for the STM32...

    The original code for the PIC16F76 is very heavily optimized for a slow 8-bit microcontroller. It uses things like virtually no stack, heavy bank switching, and lots of obscure low-level instruction tricks. From these it’s often very hard to extract 100% semantically correct code - meaning it’s difficult to perfectly reconstruct exactly what the original engineer had in mind.I’ve changed my mind on this. Porting the code 1:1 to an STM32 would be a nightmare and a massive waste of time.In my opinion, the much better approach is reverse > understanding > clean rewrite. Take the knowledge and key algorithms from the disassembly, but write everything from scratch, directly for the target 32-bit platform STM32. That way we can properly use modern solutions and implement the important parts (like the DSP core, ground tracking, etc.) cleanly in the new project.​

    Leave a comment:


  • Taktyk
    replied
    Unfortunately I had to abandon my previous attempts and mark them as legacy. I'm now doing everything from scratch once again.I’ve hidden the old versions (readable_mxt + engineered_mxt) so they don’t mix with the new code. Working with AI models turned out to be too optimistic, so I started over in src2/ – I’m reading the original ASM from MXT.TXT, mapping function by function, verifying behavior, and rewriting it in C. Claude is only helping me as support, but all the logic is manually checked by me.At the moment I have almost everything mapped and working except LCD, EEPROM and a few unclear parts.​

    Leave a comment:


  • KRinAZ
    replied
    A quick update -

    As previously mentioned I don't have blank SDIP PIC16C76's but do have SOIC's. It would of course be better to just use SDIP's in the MXT board, but I used what I have on hand...anyway...I plugged in the PIC16C76 SOIC (on the SOIC to SDIP adapter I made, pictured) that I programmed with the HEX file (elsewhere in this thread) and it operated as the original. We now know the HEX file and the disassembled code is true to the original.

    I also found an old Microchip doc that outlines the functional differences between the PIC16C76 and the PIC16F76. Although they are pin compatible, they are not functionally compatible - including differences in the contents of some file registers. I would not expect a HEX file from a C version to operate in a F version chip. If a F version is to operate in a MXT, assembly or C code will need to be used to produce a HEX file specifically for the PIC16F76.

    I'm going to take a shot at assembling code to program a PIC16F76 and test the functionality. Seems like that would be a good step towards creating code for the STM32...

    Leave a comment:


  • Taktyk
    replied
    Originally posted by KRinAZ View Post

    In case code is ever desired to be tested back in an original MXT, I have PIC16F76's that can be erased, reprogrammed, plugged into, and tested in my actual real MXT.

    I have already burned the original .HEX file (with config and ID bits) into a PIC16C76 and PIC16F76 (both SOIC). I want to establish 2 things: I can burn the HEX file back into another PIC16C76 and have it operate as the original does (to prove the HEX file is true to the original), and assuming that - I can burn to a PIC16F76 and that it also operates as the original does. The PIC16F76 datasheet says it is pin compatible with the PIC16C76 so it apparently shouldn't matter if it's a C or F PIC, both should operate the same, but seeing it work is what proves it for me.

    If amazon would ever get them to me (so much for their estimated delivery date of last week), I have SOIC to DIP adapters on the way. My early version MXT uses a DIP socketed PIC so I need the SOIC to DIP adapters to plug in the PICs that I programmed...​
    Yes, it's definitely worth confirming whether it works 100%, regardless of whether it's the C or F version. If it works, it means everything is fine and we can refine the semantic C code to make it easy to port to another platform, such as an STM32.

    I think that once I finish translating this code - which isn't easy, as I'm already on my third refactoring; it can't be done all at once, only step by step, so it will take a while – we will be able to compile it, flash it to the PIC16F76, and see if everything works.

    After that, we can choose an STM32, port the code over, and start experimenting with hardware changes - for example, a different, more efficient TX method or a better ADC, like an 18-bit SAR.

    Leave a comment:


  • KRinAZ
    replied
    Originally posted by Taktyk View Post
    I have started slowly extracting and decompiling the original code from a raw factory ROM dump of the White's MXT (PIC16C76).
    Using AI assistance, I am translating the raw assembly into clean, high-level C. So far, I have successfully extracted the core DSP logic (including the 17.5-bit oversampling, VDI phase calculations, ground balance IIR filter, and audio VCO).
    You can check out my progress on GitHub:

    https://github.com/takzen/whites-mxt...se-engineering

    My plan is to go through all 112 functions one by one. I would love to hear your thoughts and collaborate with anyone interested!
    Best regards,​​
    In case code is ever desired to be tested back in an original MXT, I have PIC16F76's that can be erased, reprogrammed, plugged into, and tested in my actual real MXT.

    I have already burned the original .HEX file (with config and ID bits) into a PIC16C76 and PIC16F76 (both SOIC). I want to establish 2 things: I can burn the HEX file back into another PIC16C76 and have it operate as the original does (to prove the HEX file is true to the original), and assuming that - I can burn to a PIC16F76 and that it also operates as the original does. The PIC16F76 datasheet says it is pin compatible with the PIC16C76 so it apparently shouldn't matter if it's a C or F PIC, both should operate the same, but seeing it work is what proves it for me.

    If amazon would ever get them to me (so much for their estimated delivery date of last week), I have SOIC to DIP adapters on the way. My early version MXT uses a DIP socketed PIC so I need the SOIC to DIP adapters to plug in the PICs that I programmed...​

    Leave a comment:


  • KRinAZ
    replied
    Originally posted by Taktyk View Post
    I have started slowly extracting and decompiling the original code from a raw factory ROM dump of the White's MXT (PIC16C76).
    Using AI assistance, I am translating the raw assembly into clean, high-level C. So far, I have successfully extracted the core DSP logic (including the 17.5-bit oversampling, VDI phase calculations, ground balance IIR filter, and audio VCO).
    You can check out my progress on GitHub:

    https://github.com/takzen/whites-mxt...se-engineering

    My plan is to go through all 112 functions one by one. I would love to hear your thoughts and collaborate with anyone interested!
    Best regards,​​
    Nice job on the github project page!

    I'll contribute where I can, you guys are ahead of me coding wise.

    Leave a comment:


  • KRinAZ
    replied
    Originally posted by Taktyk View Post
    WOW! I see the original MXT schematic. I never thought I'd actually get to see it Back in the day, I even redrew the whole thing from the PCB. That said, a lot of the circuits in it are quite outdated now, so copying it 1:1 probably isn't worth it. Conceptually though, if you modernize all the stages especially the transmitter (the original runs with too little current) and a few other sections you could end up with a really solid, high-performance detector.​
    Understood, for this project the idea is to make a functioning (in the field) MXT like detector - as close to the orig as possible - to establish a high quality prototype. White's did a fantastic job making the MXT and I think re-making a functioning MXT will be enough of a challenge - so let's get to that point first. It's (to me) easier to figure why a mod degrades a functioning prototype, than to make a bunch of changes on paper, build it, then wonder what went wrong...

    I for one have a number of fun mods in mind that would branch from the working prototype, but that is way down the road...

    Leave a comment:


  • Taktyk
    replied
    I have started slowly extracting and decompiling the original code from a raw factory ROM dump of the White's MXT (PIC16C76).
    Using AI assistance, I am translating the raw assembly into clean, high-level C. So far, I have successfully extracted the core DSP logic (including the 17.5-bit oversampling, VDI phase calculations, ground balance IIR filter, and audio VCO).
    You can check out my progress on GitHub:

    https://github.com/takzen/whites-mxt...se-engineering

    My plan is to go through all 112 functions one by one. I would love to hear your thoughts and collaborate with anyone interested!
    Best regards,​​

    Leave a comment:


  • Taktyk
    replied
    WOW! I see the original MXT schematic. I never thought I'd actually get to see it Back in the day, I even redrew the whole thing from the PCB. That said, a lot of the circuits in it are quite outdated now, so copying it 1:1 probably isn't worth it. Conceptually though, if you modernize all the stages especially the transmitter (the original runs with too little current) and a few other sections you could end up with a really solid, high-performance detector.​

    Leave a comment:


  • KRinAZ
    replied
    I have verified that the .HEX file that MPLab generated is in fact a valid .HEX file that can be directly burned to a PIC. I have the soic-28 to dip adapter pcb's that I need on order, and as soon as they arrive (probably Fri 5/15) I will burn a PIC and put it in my MXT and test for functionality.

    Assuming it works (I expect it will) I will begin converting the assembly into C as reference code for this project. BTW I'm old school and don't have AI tools so if anyone wants to run that assembly code thru Claude or something, that would be great!

    Also in the background I'm chipping away at creating a complete component list, and will soon begin the schematic with a thought towards a build procedure document.

    Leave a comment:

Working...
X