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 Taktyk View Post


    The real question is: what exactly did the AI accomplish here? xDD

    Because in my experience, the reality looked much less “magical” than the hype posts suggest.

    Claude Code + Opus 4.7 could spend hours analyzing the firmware and still not fully understand everything. The model would return to difficult functions, create separate files for unresolved code, and iteratively refine its interpretations. Honestly, that behavior inspired much more confidence because it looked closer to actual reverse engineering.

    Gemini Flash 3.5 and GPT5.5(codex), on the other hand, was extremely enthusiastic from the beginning. It spent hours generating refactors and claiming it had produced fully semantic C code. The problem appeared later when I started verifying the results carefully.

    It turned out that:
    - some functions did not even exist in the original assembly,
    - some dependencies were completely invented,
    - the model added its own logic,
    - several interpretations looked plausible but had no grounding in the actual firmware.
    This is the classic issue with current models:
    they can generate extremely convincing local explanations and code, while globally hallucinating the architecture of the entire system.

    That is why, for projects like this, raw intelligence is not enough. What matters just as much is whether the model has some form of “awareness of uncertainty”.

    Ironically, I trust a model more when it: says “I do not fully understand this yet”, revisits difficult parts iteratively, marks uncertain functions and maintains multiple hypotheses,
    than a model that very quickly claims it has completely reverse engineered an old embedded firmware system.

    Recovered and semantically reconstructed code after many hours of analysis:
    https://github.com/takzen/whites-mxt...src2/ram_map.h

    Actually when I used to work ( LOL ) .... one of my engineering tasks was protecting intellectual property. If Garrett do own the whites IP rights then blatently putting up copies / reverse engineering the firmware is a violation of copyright and could result in a takedown notice to this forum at a minimum and something more threatening at worst. ( depending on jurisdiction firmware copyright can be 70 years + ).

    I saw that you and others were doing ( presumably good work ) but you are still creating a derivative work ( by reverse engineering ) so you are back at my first statement above.

    The AI claimed to have fully decoded and extracted everything the orignal code does .. this was trivial for the AI BUT again refer to my first statement. ( so I wont be publishing it here unless someone else cares to do it).
    It did this by compiling the assembly code, running it in a simulator with code stubs that simulated all the inputs / ouputs ( like the adc, the pots, the swiches, the audio ) etc and seeing if it matched the behaviour from the schematic and the user manual. The AI looked into registers and memory in the simulator to figure out what was changing what ... this is an old hardware hacker method.

    Unlike your commendable efforts I have only shown that there is an alternate path to achieve an outcome that does not involve reverse engineering the code but infers the required internal code from looking at the behaviour of the circuit, the signals at each pin and lastly reading the fine manual ( aka RTFM ) .. .that is the AI reading the manual ... not me.

    You mention your analysis where claude etc spent hours determing the inner workings etc ... this is where context engineering comes into play.
    My approach is to look at the schematic ... what is the circuit doing at each pin. What is the signal behvaviour at each pin. What is the code that could produce that behaviour or process that signal. Then read the user manual, what are the controls, the LCD display, the boot behaviour, the switch functions ( description of each ). What is the timing of all these signals. This is the context.

    The most important part is to start generating code then run it through a compiler then a chip emulation ( cycle accurate ). Its not like there were no bugs ... there were quite a few ..particularly around interrupts. Then the AI changes the code ... runs the sim again etc. until the code runs in the sim with no errors and the timings / behaviours are all consistent.

    There is no hype here .. the interface to any LLM seems to be "hypy" in nature. I am just reporting what it was reporting to me.

    By doing a clean room build "the uncertainty" you mention is removed. Yes in the original firmware there are variables that are "uncertain what this does / is for". In hindsight there are no "magic" algorithms in the original code in fact there are quite a few shortcuts and space saving assembly kludges that were not needed since the code fits easily into the chip.

    Could there still be bugs ... absolutely ! ... but I ( err the AI ) has only spent a couple of hours on it.

    So to answer your question .. .what did the AI achieve here ? ... plenty !

    See the full assembly source attached ...

    Attached Files

    Leave a comment:


  • Taktyk
    replied
    Originally posted by moodz View Post

    The AI took maybe an hour to do this... I estimate a couple of months for an experienced engineer ( from scratch + debugging ).
    The chip utilisation shows one super power of assembly code ...

    The real question is: what exactly did the AI accomplish here? xDD

    Because in my experience, the reality looked much less “magical” than the hype posts suggest.

    Claude Code + Opus 4.7 could spend hours analyzing the firmware and still not fully understand everything. The model would return to difficult functions, create separate files for unresolved code, and iteratively refine its interpretations. Honestly, that behavior inspired much more confidence because it looked closer to actual reverse engineering.

    Gemini Flash 3.5 and GPT5.5(codex), on the other hand, was extremely enthusiastic from the beginning. It spent hours generating refactors and claiming it had produced fully semantic C code. The problem appeared later when I started verifying the results carefully.

    It turned out that:
    - some functions did not even exist in the original assembly,
    - some dependencies were completely invented,
    - the model added its own logic,
    - several interpretations looked plausible but had no grounding in the actual firmware.
    This is the classic issue with current models:
    they can generate extremely convincing local explanations and code, while globally hallucinating the architecture of the entire system.

    That is why, for projects like this, raw intelligence is not enough. What matters just as much is whether the model has some form of “awareness of uncertainty”.

    Ironically, I trust a model more when it: says “I do not fully understand this yet”, revisits difficult parts iteratively, marks uncertain functions and maintains multiple hypotheses,
    than a model that very quickly claims it has completely reverse engineered an old embedded firmware system.

    Recovered and semantically reconstructed code after many hours of analysis:
    https://github.com/takzen/whites-mxt...src2/ram_map.h

    Leave a comment:


  • moodz
    replied
    Click image for larger version

Name:	image.png
Views:	122
Size:	68.6 KB
ID:	449066
    Click image for larger version

Name:	image.png
Views:	108
Size:	62.1 KB
ID:	449067
    Click image for larger version

Name:	image.png
Views:	110
Size:	106.6 KB
ID:	449068
    Click image for larger version

Name:	image.png
Views:	104
Size:	50.9 KB
ID:	449069
    Click image for larger version

Name:	image.png
Views:	109
Size:	153.7 KB
ID:	449070​​​

    Leave a comment:


  • moodz
    replied
    Originally posted by Aziz View Post
    The gardener is always the murderer. In this case to the secrets of the source/binary code.


    BTW, regarding the averaging of the phases in the code.
    Never average the phase angles. Do it in the I/Q part and average the I and Q parts. Than calculate the phase, when it is required.

    Good job Paul!


    Leave a comment:


  • moodz
    replied
    Originally posted by boilcoil View Post
    This AI is a sly one.
    Interestingly, there were no compilation inconsistencies due to the unspecified "paging" for the programs in the second page, called by the main program -
    call dsp_filter
    call dsp_ground
    call dsp_metrics ...
    But since everything works, there is obviously no problem.​
    this is what the AI said ...

    Click image for larger version

Name:	image.png
Views:	132
Size:	381.2 KB
ID:	449062

    Leave a comment:


  • Aziz
    replied
    Originally posted by moodz View Post
    The AI did all this whilst I was gardening ... its prepping the docs now.
    The gardener is always the murderer. In this case to the secrets of the source/binary code.


    BTW, regarding the averaging of the phases in the code.
    Never average the phase angles. Do it in the I/Q part and average the I and Q parts. Than calculate the phase, when it is required.

    Good job Paul!

    Leave a comment:


  • boilcoil
    replied
    This AI is a sly one.
    Interestingly, there were no compilation inconsistencies due to the unspecified "paging" for the programs in the second page, called by the main program -
    call dsp_filter
    call dsp_ground
    call dsp_metrics ...
    But since everything works, there is obviously no problem.​

    Leave a comment:


  • moodz
    replied
    Done .. complete clean room build in pin for pin chip ( 16F876A ) for the MXT schematic. They still make the 16F876 in a DIP chip so its good for all you oldtimers.
    Math is 32bit and CORDIC. 100% assembly code.
    24 bit ADC support ( would need to be an SDI chip .. and some small additional code to support ) but easily fits in the timing cycle. ( 4 ms ).

    The AI took maybe an hour to do this... I estimate a couple of months for an experienced engineer ( from scratch + debugging ).
    The chip utilisation shows one super power of assembly code ....

    Click image for larger version

Name:	image.png
Views:	95
Size:	302.2 KB
ID:	449057





    Click image for larger version

Name:	image.png
Views:	125
Size:	262.0 KB
ID:	449056

    Leave a comment:


  • moodz
    replied
    The AI did all this whilst I was gardening ... its prepping the docs now.


    Click image for larger version

Name:	image.png
Views:	106
Size:	96.7 KB
ID:	449052


    Leave a comment:


  • moodz
    replied
    it lives ! ( on the simulator )

    this means the code compiles and runs ( on a 3rd party simulator not mine ).

    === adc_sample=40000 : printable runs (>=6 chars) in SPI stream ===
    .......OpenMD 1.0 BATT 133 .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. ...........VDI-95 ........ DP255 BT133 GND .................................................. ............................................VDI-95 ........ DP255 BT133 GND .................................................. ............................................VDI-95 ........ DP255 BT133 GND .................................................. ............................................VDI-95 ........ DP255 BT133 GND .................................................. ............................................VDI-95 ........ DP255 BT133 GND .................................................. ............................................VDI-95 ........ DP255 BT133 GND .................................................. ............................
    === adc_sample=8000 : printable runs (>=6 chars) in SPI stream ===
    .......OpenMD 1.0 BATT 133 ...........................................​

    Leave a comment:


  • moodz
    replied
    ... here is the main asm file ... the AI is doing the simulation and debugging now.

    ;================================================= =============================
    ; openmd.asm -- OpenMD : clean-room VLF metal-detector firmware
    ; PIC16F876A, 8 MHz HS. (c) my own original authorship.
    ;
    ; Clean-room: derived solely from CLEANROOM_SPEC.md, the schematic, the user
    ; manual, the PIC16F876A + external-chip datasheets, and public VLF theory.
    ; No prior firmware, dump, or disassembly was consulted. Build name "OpenMD".
    ;
    ; Build (16-bit default): gpasm -p 16f876a src/openmd.asm -o build/openmd.hex
    ; Build (24-bit) : gpasm -D ADC_BITS=24 -p 16f876a src/openmd.asm ...
    ;
    ; Program map (all in page 0, 0x000..0x7FF):
    ; 0x000 reset, 0x004 ISR, 0x100/0x200 string tables, 0x300+ code.
    ;================================================= =============================

    list p=16f876a, r=dec
    errorlevel -302 ; silence "register not in bank 0" (banksel used)
    errorlevel -306 ; silence "crossing page boundary" info on tables we page-align
    errorlevel -1302 ; silence "RAM bank undefined" info (banksel is explicit)
    #include <p16f876a.inc>

    #include "config.inc"
    #include "hw.inc"

    __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _BOREN_ON & _LVP_OFF & _CP_OFF

    #include "vars.inc"
    #include "fixed.inc" ; macros only (no code emitted)

    ;================================================= =============================
    ; Reset + interrupt vectors
    ;================================================= =============================
    org 0x000
    goto start

    org 0x004
    ;------------------------------------------------------------------------------
    ; ISR : conventional context save/restore; Timer1 -> set frame flag, reload.
    ;------------------------------------------------------------------------------
    isr:
    movwf w_temp
    swapf STATUS, W
    movwf status_temp
    movf PCLATH, W
    movwf pclath_temp
    clrf PCLATH ; ISR body lives in page 0: force page bits 0

    banksel PIR1
    btfss PIR1, TMR1IF
    goto isr_exit
    bcf PIR1, TMR1IF
    banksel TMR1H
    movlw T1_PRE_H
    movwf TMR1H
    movlw T1_PRE_L
    movwf TMR1L
    bsf flags, F_FRAME ; flags is common RAM (no bank issue)

    isr_exit:
    movf pclath_temp, W
    movwf PCLATH
    swapf status_temp, W
    movwf STATUS
    swapf w_temp, F
    swapf w_temp, W
    retfie

    ;================================================= =============================
    ; Code (flows right after the ISR; all in page 0, < 0x0800)
    ;================================================= =============================
    start:
    ; --- bank1 SFRs: TRIS, ADC justify, pull-ups, PWM period, interrupts ---
    banksel TRISA
    movlw TRISA_INIT
    movwf TRISA
    movlw TRISB_INIT
    movwf TRISB
    movlw TRISC_INIT
    movwf TRISC
    movlw ADCON1_INIT
    movwf ADCON1
    movlw 0x00 ; OPTION_REG: /RBPU=0 (PORTB pull-ups on)
    movwf OPTION_REG
    movlw TX_PR2
    movwf PR2
    movlw (1<<TMR1IE) ; PIE1: Timer1 interrupt
    movwf PIE1

    ; --- bank0 SFRs ---
    banksel PORTA
    clrf PORTA
    clrf PORTB
    clrf PORTC
    movlw ADCON0_BASE
    movwf ADCON0
    bcf STATUS, IRP ; indirect addressing targets banks 0/1

    call clear_ram

    ; --- defaults (bank0) ---
    banksel mode
    clrf mode ; Coin & Jewelry
    movlw d'2'
    movwf trac ; Ground-On

    call spi_init
    call pwm_init
    call timer1_init

    ; --- splash for ~1 s (244 frames) ---
    call acquire_frame ; get a battery reading for the splash
    call build_splash
    call lcd_flush
    banksel splash
    movlw d'244'
    movwf splash

    bsf INTCON, PEIE
    bsf INTCON, GIE

    ;------------------------------------------------------------------------------
    ; main loop : one pass per 4 ms frame tick
    ;------------------------------------------------------------------------------
    main_loop:
    btfss flags, F_FRAME
    goto main_loop
    bcf flags, F_FRAME

    call acquire_frame
    call check_battery

    banksel splash
    movf splash, F
    btfsc STATUS, Z
    goto ml_search ; splash done -> search
    decf splash, F
    goto ml_end ; still showing splash

    ml_search:
    call read_switches
    call dsp_filter
    call dsp_ground
    call dsp_metrics
    call dsp_vdi
    call dsp_strength_depth
    call dsp_discriminate
    call audio_update

    ; repaint the LCD every 8 frames (~32 ms) to keep SPI traffic light
    banksel framecnt
    incf framecnt, F
    btfsc STATUS, Z
    incf framecnt+1, F
    movf framecnt, W
    andlw 0x07
    btfss STATUS, Z
    goto ml_end
    call build_search
    call lcd_flush

    ml_end:
    call spi_resync ; keep the shared bus on a 48-bit boundary
    goto main_loop

    ;------------------------------------------------------------------------------
    ; clear_ram : zero GPR 0x20..0x7F and 0xA0..0xEF (IRP=0 indirect).
    ;------------------------------------------------------------------------------
    clear_ram:
    bcf STATUS, IRP
    movlw 0x20
    movwf FSR
    cr1:
    clrf INDF
    incf FSR, F
    movlw 0x80
    subwf FSR, W
    btfss STATUS, C
    goto cr1
    movlw 0xA0
    movwf FSR
    cr2:
    clrf INDF
    incf FSR, F
    movlw 0xF0
    subwf FSR, W
    btfss STATUS, C
    goto cr2
    return

    ;------------------------------------------------------------------------------
    ; pwm_init : CCP1 PWM on RC2 ~13.9 kHz, 50% (Timer2 time-base).
    ;------------------------------------------------------------------------------
    pwm_init:
    banksel CCPR1L
    movlw TX_DUTY_H
    movwf CCPR1L
    movlw b'00001100' ; CCP1CON: PWM mode, DC1B=00
    movwf CCP1CON
    movlw b'00000100' ; T2CON: TMR2ON=1, prescale 1:1
    movwf T2CON
    return

    ;------------------------------------------------------------------------------
    ; timer1_init : 4 ms frame tick, internal clock, 1:1, preloaded.
    ;------------------------------------------------------------------------------
    timer1_init:
    banksel T1CON
    movlw b'00000001' ; TMR1ON=1, 1:1, internal
    movwf T1CON
    movlw T1_PRE_H
    movwf TMR1H
    movlw T1_PRE_L
    movwf TMR1L
    banksel PIR1
    bcf PIR1, TMR1IF
    return

    ;------------------------------------------------------------------------------
    ; check_battery : set/clear F_LOWBATT from vbatt vs LOWBATT_CNT (10-bit).
    ;------------------------------------------------------------------------------
    check_battery:
    banksel vbatt
    movf vbatt+1, W
    sublw high(LOWBATT_CNT) ; (hi_thr) - vbatt_hi ; C=1 if vbatt_hi <= hi_thr
    btfss STATUS, C
    goto cb_ok ; vbatt_hi > threshold hi -> ok
    movf vbatt+1, W
    btfsc STATUS, Z
    goto cb_low ; vbatt_hi == 0 (< 256) -> low
    movlw low(LOWBATT_CNT)
    subwf vbatt, W ; vbatt_lo - thr_lo ; C=1 if >= -> ok
    btfsc STATUS, C
    goto cb_ok
    cb_low:
    bsf flags, F_LOWBATT
    return
    cb_ok:
    bcf flags, F_LOWBATT
    return

    ;------------------------------------------------------------------------------
    ; read_switches : 2-phase diode-matrix scan -> mode (phase1) + trac (phase2).
    ; Each 3-position toggle grounds one of RB2/RB3/RB4 in its scan phase.
    ; No return active -> keep previous value (debounce-by-hold).
    ;------------------------------------------------------------------------------
    read_switches:
    banksel PORTB
    ; ---- phase 1: MODE (scan = RB1 low, RB5 high) ----
    bsf PORTB, SW_SCAN2
    bcf PORTB, SW_SCAN
    nop
    nop
    nop
    comf PORTB, W ; active-low returns -> 1 = pressed
    andlw SW_RET_MASK
    movwf t0
    btfsc t0, SW_RET0
    clrf mode ; RB2 -> Coin & Jewelry
    btfsc t0, SW_RET1
    goto rs_mode1
    btfsc t0, SW_RET2
    goto rs_mode2
    goto rs_trac
    rs_mode1:
    movlw d'1'
    movwf mode
    goto rs_trac
    rs_mode2:
    movlw d'2'
    movwf mode
    rs_trac:
    ; ---- phase 2: TRAC (scan = RB5 low, RB1 high) ----
    banksel PORTB
    bsf PORTB, SW_SCAN
    bcf PORTB, SW_SCAN2
    nop
    nop
    nop
    comf PORTB, W
    andlw SW_RET_MASK
    movwf t0
    btfsc t0, SW_RET0
    clrf trac ; RB2 -> Salt-Beach
    btfsc t0, SW_RET1
    goto rs_trac1
    btfsc t0, SW_RET2
    goto rs_trac2
    goto rs_done
    rs_trac1:
    movlw d'1'
    movwf trac ; Hold-Lock
    goto rs_done
    rs_trac2:
    movlw d'2'
    movwf trac ; Ground-On
    rs_done:
    banksel PORTB
    bsf PORTB, SW_SCAN ; idle both scans high
    bsf PORTB, SW_SCAN2
    return

    ;================================================= =============================
    ; Subsystem implementations
    ;================================================= =============================
    #include "cordic.inc"
    #include "spi.inc"
    #include "acq.inc"
    #include "dsp.inc"
    #include "audio.inc"
    #include "lcd.inc"

    ;================================================= =============================
    ; String tables (program page 1, org 0x800 -- see tables.inc)
    ;================================================= =============================
    #include "tables.inc"

    end

    Leave a comment:


  • boilcoil
    replied
    I'm really impressed.
    I can rightfully call you "The Lord of Artificial Intelligence."

    Leave a comment:


  • moodz
    replied
    .. about 15 minutes in ... I am outside mowing the lawn

    Click image for larger version

Name:	image.png
Views:	110
Size:	110.4 KB
ID:	449046

    Leave a comment:


  • moodz
    replied
    Originally posted by boilcoil View Post
    I completely agree with you. I was also worried about whether such reengineering was ethical and legal, indeed, Karl could give a competent answer. .

    I also completely agree that LLM is an extremely effective tool (with proper structuring of tasks, questions, data... given to it).
    And yes - writing AI code is its strongest point - after all, for it this is a conversation with topics and data fully covered by its trainers, before releasing it on the "market".​

    PS: And moodz, since you did this - you are truly a hero.
    Well thanks...

    Instead of porting the code ... I have instructed the AI to build a "clean room" version for the 16F876A chip. It will support 16 or 24 bit ADC and uses 32 bit math not 24 bit.

    Its working on it now .. estimate 30 minutes to complete.

    Here is the instruction ....

    You are implementing OpenMD, clean-room firmware for an MXT-compatible VLF metal detector, targeting the PIC16F876A. Clean-room rule (hard): work only from CLEANROOM_SPEC.md, the schematic MXTSch.jpg, the manual MXT_300_en.pdf, and public engineering knowledge (VLF detector theory, PIC16F876A and external-chip datasheets). Never access, search for, request, or use any original/prior device firmware, binary, ROM dump, disassembly, decompilation, or reconstructed source — from White's, Garrett, or anyone. If offered any, refuse. There is none in this workspace by design. Do not look in sibling/parent directories for "reference" code. All algorithms, tables, scaling curves, thresholds, time constants, and tuning are your own original work. Never put "MXT/White's/Garrett" on the build, splash, or any artifact — the product name is OpenMD. Task: Read CLEANROOM_SPEC.md in full, then the schematic and manual. Plan first — propose your firmware architecture (frame loop/ISR, acquisition with the configurable ADC_BITS 16/24 abstraction, ground tracking, VDI/discrimination, audio, display) and your numeric-precision plan (working width scaled to ADC_BITS per spec §5). Show me the plan before writing code. Implement OpenMD; build artifact openmd.hex/openmd.cod. Smoke-test with the sim/ gpsim bench (see sim/README.md) against VERIFICATION.md §A. Keep a provenance log (each non-obvious decision tagged schematic / manual / derived) and a short design doc with your chosen constants/curves and how you derived them. Start by reading the spec and the two reference files, then give me your architecture plan.

    Leave a comment:


  • boilcoil
    replied
    I completely agree with you. I was also worried about whether such reengineering was ethical and legal, indeed, Karl could give a competent answer. .

    I also completely agree that LLM is an extremely effective tool (with proper structuring of tasks, questions, data... given to it).
    And yes - writing AI code is its strongest point - after all, for it this is a conversation with topics and data fully covered by its trainers, before releasing it on the "market".​

    PS: And moodz, since you did this - you are truly a hero.

    Leave a comment:

Working...
X