Ralim / IronOS

Open Source Soldering Iron firmware
https://ralim.github.io/IronOS/
GNU General Public License v3.0
7.28k stars 723 forks source link

Miniware MHP30 HotPlate Firmware Support #822

Closed vini-nu closed 3 years ago

vini-nu commented 3 years ago

What about supporting MHP30 ? From the feature side it is very similar to ts80p. Externally it is basically the same iron (A B buttons, one OLED screen, type c pd and hotplate_vs_tip ), just in hotplate form factor.

It's menu is also very similar to default firmware for TS80P and TS100 (including menu icons).

What do you think about it ? @Ralim

I have it in hands, can send more info. Maybe pics of internals. Etc. Personally I could sit down to coding this, but that would be in mid-summer sadly.

PS. Official hardware page: http://www.miniware.com.cn/product/mhp30-mini-hot-plate-preheater/ Official MHP30 firmware: https://www.minidso.com/forum.php?mod=viewthread&tid=4385&extra=page%3D1 TypeC PD 20V/60W (Max); Meanwhile on 65W PD supply, display shows 59W on cold-start. 100'C-350'C; Through it could definitely work in wider low-temp range.

vini-nu commented 3 years ago

Pics of insides (2 screws total):

image image image image image image image image image

DjordjeMandic commented 3 years ago

Was it worth? What are the performances compared to proper IR preheater?

Ralim commented 3 years ago

Hmm this is an interesting little unit.

I hadn't looked into it much up until now.

Definitely looks like it could be supported, feels like controls would be very similar with just all the motion based stuff turned off.

Main issue is figuring out what parts they have used and how they are connected. Have had it easier in the past as they have released schematics.

I'll email and ask but unsure if they will be willing to release them yet 😂

If we can get schematics happy to look at adding support

DjordjeMandic commented 3 years ago

@Ralim i bet they will release it at least to you or just send you pin map and explanations. Your firmware also gets them more customers. I bought TS80 just because you supported it.. :) Huge respect!

vini-nu commented 3 years ago

image image

@Ralim Looks like it has motion sensor (for tilt & drop protection). If I tilt it 50degrees while in soldering-mode, it starts beeping and red blinking with "/!\Warning" on display (and cuts off temperature). Then bringing it back, it goes back to main-menu. Oh and forgot to tell, it has volume regulated beeper and 1 RGB LED. It probably should be using different code-strategy for MHP30 motion sensor in IronOS.

@DjordjeMandic I bought it to preheat PCB near-melting point so it would be easier to solder with soldering-iron, because melting-point is relatively-lowered. Especially for lead-free solder which normally has higher melting-point. --- Too early to tell if it was worth it, I have nothing to compare it to, but it does feels high-quality. Also it has silicon cap, so hotplate doesn't scratch then not in-use.

Ralim commented 3 years ago

So my feelings on this are that it could basically run a variant of IronOS; and we could just have an extension to the current accelerometer code to detect tilt (rather than activity).

Most of the things that we would want on something like this i feel already exist in this firmware, with mostly just some changes to how movement is used; and adding support for a buzzer.

I'm interested in this little one for reflowing on BGA packages. I have a few projects that use the Recom RPM5.0-6.0 dc/dc convertors and it would make doing qfns a bit simpler when i dont want to setup full on reflow.

I did reach out to my contact at Miniware but so far:

  1. Not giving me schematics or pinouts 😢
  2. This unit has bootloader as part of main firmware rather than as seperate

(1) is a bit of a pest as without schematics we would need to trace out all the connections on the board. (2) is no big deal at all, as we can at the least flash a dfu bootloader to the first 8k :)

I noticed there are test points labelled A/B/C/D/E/F/G. Guessing by the looks that:

Would be ideal to confirm if we have SWD or not. If we do then could try and extract the firmware to confirm flash is 1:1 with what they upload (given they are baking in the bootloader it may not be).

I'm thinking I'll pick one of these up at the end of the month, but it could be a while until i make progress on it due to busy life / actual job :D

gordon-quad commented 3 years ago

Just a thought: it would be awesome to have some sort of poor man's reflow profile support on that device, just set soak temp/soak time/peak temp/peak time w/o slope control and use PID for reaching those temps.

Would be great for reflowing tiny usb-stick-sized pcbs.

AlessandroAU commented 3 years ago

This would be awesome for reflowing small PCBs, I have one too, let me know how I can help.

AlexKlimaj commented 3 years ago

I can confirm that it is a great little product. Bringing IronOS to it would be a nice addition. ExONE6aVIAETccA

g3gg0 commented 3 years ago

would also love to see a custom firmware for it.

came across various use cases which can be addresses using profiles

so if you could manage to add support, this would be very cool.

fivsic commented 3 years ago

Hi, Just bought the MHP30 and it works nicely except the tilt angle detector. With deactivation of the tilt angle detection, it's ok This parameter in not included in the config.txt file, so i have to deactivate each time the device is turned on

I fully agree with the g3gg0 proposal

(Software version : 2.01, Hardware vers : 1.50)

best regards

ExplodingWaffle commented 3 years ago

https://www.pine64.org/2021/04/15/april-update-new-developments/ The pinecil is getting a hammerhead tip, that cooould be used for reflowing tiny pcbs also 🤔 I'd love to see software support in IronOS for reflow profiles and the like.

Ralim commented 3 years ago

So I have started to look into this. The MHP30 is interesting for a few reasons:

  1. The USB-bootloader is now integrated somewhat into their firmware
  2. The flash readout was not enabled on my unit, but flashing back a 64k dump didnt work, so suspect they are using more than the stock flash capacity somewhere (or i tripped something).
  3. Miniware are refusing to share any docs at all on the unit, so like the TS80P back to multimeter probing to get pinout
  4. SWD is available on the USB-C using the data pins like the TS80/TS80P/ later TS100's.
  5. These are on D+=SWDIO, D-=SWCLK

I've started trying to figure out pinouts but nothing much to report yet. Editing this message as I go.

If someone is willing to (possibly risk) trying to dump the firmware from their device, would love a dump of the flash (try 128k/256k dumps maybe? Please dont do this unless you know what your doing :)

Pinout notes:

TODO:

Things to do:

  1. [x] Bring up OLED
  2. [ ] Probe what unknown chip is
  3. [x] Figure out what Accel is in use
  4. [ ] Test USB-PD
  5. [x] Heater element PWM control
  6. [ ] Cold junction temp sensor
  7. [ ] Check all ADC input channels
  8. [ ] Figure out how to handle bootloader (can we keep theirs or use the dapboot fork)
g3gg0 commented 3 years ago

Hmm happen to have an Lauterbach TRACE32 with Cortex-M License lying around. Will try to solder an adapter and try my luck if the license still works.

g3gg0 commented 3 years ago

Here the Flash dump. Didnt check the datasheet, just saw 0x08000000--0x0801FFFF. Is there anything else to dump?

MHP30.zip

And here a register dump during runtime. regs.txt

Unfortunately the debugger is being disconnected after a few seconds if it is also reading from the memories while the software is running. Couldnt find out why.

g3gg0 commented 3 years ago

update: made a break while in main menu and dumped hopefully also RAMs in a consistent state. MHP30.zip

g3gg0 commented 3 years ago

will upload binary files, the hex files of this lauterbach version seem weird. missing the field for the upper 16 bits of the memory address.

MHP30.zip

ADCs: ADC_IN0: hotplate indicator? 0x6E9 when connected, 0xFDA when open ADC_IN1: seems the 5V rail (0x29C: 5.22V, 0x2A4: 5.3V) ADC_IN2: hotplate temperature sensor (0x148 when around 22°C, rising when higher) ADC_IN6: 0x17C ADC_IN8: 0xD0B ADC_IN9: 0xA5C

configured pins: (added your findings) PA0 IN (analog) hotplate_indicator? PA1 IN (analog) VIN sense PA2 IN (analog) hotplate_temperature PA3 IN (floating) toggled contiuously in main if some flags set PA4 OUT: toggled when measuring heater resistance PA5 IN (analog) PA6 IN (analog) PA7 OUT (pushpull) Buzzer PA8 OUT (pushpull) LED switches to green if toggled manually PA9 OUT (alternate pushpull) SK6812 PA10 IN (pull-up) Button A PA11 OUT (alternate pushpull) USB PA12 OUT (alternate pushpull) USB PA13 IN (floating) SWD PA14 IN (floating) SWD PA15 OUT (open drain) OLED_SDA

PB0 IN (pull-up) Button B PB1 IN (analog) PB2 IN (floating) PB3 OUT (open drain) OLED_SCL PB4 OUT (pushpull) OLED_RST PB5 IN (pull-up) PB6 OUT (open drain) I2C1 PB7 OUT (open drain) I2C1

PD0 OUT (open drain) toggled in some unidentified code. seems some communication PD1 IN (floating) toggled when measuring hotplate temperature

g3gg0 commented 3 years ago

more findings:

update: image found where the IWDT is enabled, was able to break and bypass IWDT enabling. so i am now able to fully debug and single step the original code (but only with 5V, so no heating)

Ralim commented 3 years ago

That is awesome 🥳 thank you.

I'll have a dig later on today when back home to see how this lines up.

Thank you for also poking the IO. I have managed to acquire a pinout for the fet module used to will re-trace that and it should hopefully make more sense

g3gg0 commented 3 years ago

you're welcome, thats the least i can do.

hoped that PA8 is the hotplate control mosfet, because the software switches the LED to green if enabled. the software immediately switches the pin off again. but with 5V applied the current doesnt raise at all if the pin is enabled. so either the mosfet shuts down if the voltage is too low (is it that intelligent?) or we are missing an output.

Ralim commented 3 years ago

From your testing I suspectPA8 is the enable signal that I was missing + the PWM I think I found earlier.

Will test when I can and then report back :)

Your spotting PA4 as an output is odd, not what I was expecting.

I'll need to re-trace that input.

If you have time, would be curious if you spot any of the analog inputs changing with room temperature; as haven't found a suspect for the that really. Could be PA0 (adc0).

But can totally leave that until later on at first.

Also really curious what PA4 is for, as it seemed to drift with PCB temperature the most (using PCB cleaner to cool board) but could just be high impedance that the cleaner is affecting.

Ralim commented 3 years ago

Update: Flashing your flash backup back to the unit does not want to let me use the unit (its locking me in a "demo mode" ?)

Butt, some progress :) I have heating element turning on now!

PA6 is the PWM input to the driver FET PA3 is the enable to the fet but its ac coupled (via a diode), so has to be toggled to keep the output alive. This is similar to the TS100 setup so not an issue. But also explains why turning all IO high didnt turn it on :)

PA8 is now a mystery though.

So updated list is: Bold means unknown

PA0 IN (analog) ?hotplate_indicator? PA1 IN (analog) VIN sense PA2 IN (analog) hotplate_temperature PA3 OUT TIM2_CH4 Heater EN Ac coupled PA4 OUT: causes SWD to fail periodically PA5 IN (analog) PA6 TIM3_CH1 - Heater PWM control PA7 OUT (pushpull) Buzzer PA8 OUT (pushpull) ? PA9 OUT (alternate pushpull) SK6812 PA10 IN (pull-up) Button A PA11 OUT (alternate pushpull) USB PA12 OUT (alternate pushpull) USB PA13 IN (floating) SWD PA14 IN (floating) SWD PA15 OUT (open drain) OLED_SDA

PB0 IN (pull-up) Button B PB1 IN (analog) PB2 IN (floating) (Looks to be pulled to gnd? -- res in corner of board near TP A) PB3 OUT (open drain) OLED_SCL PB4 OUT (pushpull) OLED_RST PB5 IN (pull-up) - IRQ - FUSB302 PB6 OUT (open drain) I2C1 PB7 OUT (open drain) I2C1

PD0 OUT (open drain) ? PD1 IN (floating) ?

I'm guessing that PB2/PA8 might go to the unknown IC to on the board (near TP A) I have zero idea what PD0/PD1 go to though.


That all said, this is enough I'm going to start work bringing up some of this :)

g3gg0 commented 3 years ago

good work. that demo mode string i have seen and wondered how to enter :D

where do the traces of the unknown ic go to? is it somewhat "isolated" and just connects to the µC or does it have some external stuff going on? like a shunt resistor in power path or similar.

Ralim commented 3 years ago

good work. that demo mode string i have seen and wondered how to enter :D

Now I just want to know how to exit lol :D

where do the traces of the unknown ic go to? is it somewhat "isolated" and just connects to the µC or does it have some external stuff going on? like a shunt resistor in power path or similar.

In this image : https://user-images.githubusercontent.com/6695244/105535323-6d939c80-5cf7-11eb-85a4-44f05b274208.png

Its the one near the B/C/D/E test points.

It seems fairly isolated off by itself, but it looks to be connected to the OLED's I2C bus. So going to try and probe its I2C address to narrow down the search space.

g3gg0 commented 3 years ago

maybe an external I²C eeprom?

g3gg0 commented 3 years ago

Now I just want to know how to exit lol :D

isn't this a great motivation to get a IronOS version working on it? :D

Ralim commented 3 years ago

maybe an external I²C eeprom?

I'm hoping its something like that and therefore we can mostly ignore it

isn't this a great motivation to get a IronOS version working on it? :D

Too true 😆

g3gg0 commented 3 years ago

How did you flash your device with my dump?

Assuming the flashing really was successful, it sounds like the flash image contains some NV data which is somehow linked to the device id - or an external information source like an EEPROM. But then I wonder why you place an external EEPROM if you already have NV data area.

g3gg0 commented 3 years ago

ok here the solution to your "DEMO MODE" issue.

this is the culprit code that causes your device to lock in "Demo mode" image

after some more reversing and decompiling, this is the result: image

this tells us that the firmware is loading the signature bytes from 0x1FFFF7E8 (Unique device ID register), and comparing it with the content of the bytes at 0x08007FF2 - where every word gets XORed with 0x80007FF2. if the content doesnt match -> lock into DEMO MODE

didn't check if there are checksums, but you could try patching the content accordingly. or just patch the code: image

replace the 0xD1 with a 0xE0, that should give an unconditional jump.

g3gg0 commented 3 years ago

what i find interesting is

is it some kind of MPU trapping and writing GPIO in trap handler thingie? or is the memory remapped?

shall i go that deep into the rabbit hole? :D

Ralim commented 3 years ago

ok here the solution to your "DEMO MODE" issue.

this is the culprit code that causes your device to lock in "Demo mode" image

after some more reversing and decompiling, this is the result: image

this tells us that the firmware is loading the signature bytes from 0x1FFFF7E8 (Unique device ID register), and comparing it with the content of the bytes at 0x08007FF2 - where every word gets XORed with 0x80007FF2. if the content doesnt match -> lock into DEMO MODE

didn't check if there are checksums, but you could try patching the content accordingly. or just patch the code: image

replace the 0xD1 with a 0xE0, that should give an unconditional jump.

OMG 🤯 Thats far more than I was expecting anyone to do. Definitely going to give the patch a try to see. 🤟🏼

is it some kind of MPU trapping and writing GPIO in trap handler thingie? or is the memory remapped?

That pattern reeks of a bit-banged I2C Like an unwrap of the code I'm using.

Is it not picking up the bit set-reset memory positions perhaps? I think 0x4221818C might be in gpio space?

g3gg0 commented 3 years ago

yeah its in SFR space, but cannot find anything that is mapped there. image datasheet says this is reserved.

yet it does write accesses and bitbanging. i really gues thats an ""elegant"" way using traps and decoding :D

the "I2C1" you mentioned on PB6/PB7 is being used with the address 0x26 in one part of the code first it sends 0x00 0x24 then a buffer at 0x8005A4C with this data: 0x0F 0x00 0x11 0x4C 0x10 0x05 0x16 0x07 0x17 0x10 0x19 0x00 0x21 0x8F 0x28 0x12 nothing more i could find for 0x26

it is also used for 0x22, but thats a lot more effort to find out what it does. could post screenshots if you wish.

Ralim commented 3 years ago

Welp holy crap, managed to get the patch to work :O

  1. Patched your flash dump and reflashed
  2. -> Device hangs at logo
  3. Entered DFU mode and reflashed the 2.0 firmware
  4. -> Now stuck at demo mode
  5. Dumped flash again and re-did the patch
  6. Unit works perfectly now

This is the final flash contents that works for me unit fwiw. D2.zip

Hella kudos to you @g3gg0

it is also used for 0x22, but thats a lot more effort to find out what it does. could post screenshots if you wish. That is the USB-PD stack.... avoid for your sanity :)

the "I2C1" you mentioned on PB6/PB7 is being used with the address 0x26 in one part of the code

I've narrowed it down, it looks like the MSA301 which we already have a driver for 😂

Just tuned in the ADC for input voltage and next is looking at the thermocouple circuit.

If you get time (zero pressure, you're already doing far more than I expected 🤟🏼 ) Would love if you poked their ADC setup, as still havent found the cold junction temp sensor yet (reliably)

Playing around with the tip, it certainly feels like the internal sensor is a K type thermocouple (or very close -- good enough for first pass).

So thats next up I think :)

g3gg0 commented 3 years ago

further findings:

pressing A long gives a screen that shows: R5.6 Type:BS30 Temp: 29C V:5.2 That R value may be the temperature (in ohms) and the BS30 seems to come from the 100 Ohms between the two outer pins of the three pins of the hotplate. limits are 90-110 ohms according to the code.

regarding adc setup: image image image image

ADC channel 1 is being read like this: image the decompiler cannot really decode a lot of stuff, like the softfloat or the functions only setting flags, but not registers.

it reads ADC#1, checks if it is less than 65535 (looks like) and stores that value or returns the last stored one. then it does a / 3.3 / 110.0 * 40960.0 ??

g3gg0 commented 3 years ago

for the temperature, the code does: retrieve cached ADC#5 value (float) which may include some delta-reading (GPIO on, read ADC, GPIO off, read ADC, delta, things...) read ADC#2 three times and average (float) read ADC#9 three times and average (integer) lookup using averaged ADC#9 value in 0x08013230 (PCB temperature sensor?) value of lookup gets stored in lookup table at 0x20003298 (which goes from 0x65 to 0xE56) and the result looks like ambient temperature (26.048).

then things go on. they are tedious to trace. maybe the numbers in the comments help you? image

g3gg0 commented 3 years ago

not sure if it helps. here a flow chart of how the firmware calculates the hotplate temperature.

image

F{A, B} are unknown float functions DB is a unknown double function, DA is DIV, DC is MUL, DD is ADD, DB might be SUB then? unknown, as i am just guessing what it is. the upper "arrow-in" is the first argument, the lower the second.

edit: updated the image and filled the missing functions

g3gg0 commented 3 years ago

Hint PD1 is being reconfigured as output during ADC5 read. (updated) image

here you can see the "ADC#5 magic" block from the image above

and here the hotplate calc function reverse engineered to C image

Ralim commented 3 years ago

OMG. Your decompiling is faster than me poking the pcb.

it reads ADC#1, checks if it is less than 65535 (looks like) and stores that value or returns the last stored one. then it does a / 3.3 / 110.0 * 40960.0 ??

value * 3.3/4096 == convertion to Volts The 1100 value is odd though to me, unless they are factoring into this equation the gain of the op-amp ? Something akin to how this firmware works in uV readings.

the BS30 seems to come from the 100 Ohms between the two outer pins of the three pins of the hotplate. limits are 90-110 ohms according to the code.

Did you spot where they are measuring the 90-110 ohms? (Sorry if ive missed it in the above).

In the past they have used a pin toggle like that to measure tip resistance (by knowing current through pullup resistor you can calculate the tip resistance by using it as a voltage divider to ground.

But looking at the code flow it doesnt feel like that.. though.. (A-B/(4096+B-A))*1000 feels like they are calculating a percentage of some form. Perhaps the 100 ohm resistor on the heating element is used to indicate a gain value for the top / what kind of thermocouple it is?

That diagram is worth far more than you understand

I'm thinking I need to trace out the ADC5 pin a bit better on this board to get an idea of what it is measuring.

Ralim commented 3 years ago

Looking at ADC pin 9 for the cold junction temp, it lines up particularly well with being the same NTC as the TS80P uses. Testing this now :)

g3gg0 commented 3 years ago

hehe. happy to see you working on a potential port to it ;)

findings: the code is - as you can see in the hex file - partitioned. you have some kind of bootloader which sets up a lot of stuff the main firmware also does. but then it only checks for the PA10 being low (button A) if so, it handles DFU mode - else - it jumps to main firmware.

unfortunately the address ranges are quite intermixed. RESET -> 0x08006334 -> 0x080062C8 -> 0x08002522 -> [table@0x08008004] -> 0x080144E8 (main)

Ralim commented 3 years ago

table@0x08008004 is very standard which is good.

That chain is looking... Fairly sane.

It seems to jump around below 8000 first which is an area we don't touch and then after that it jumps into the reset vector of the new firmware.

I think we should be okay w.r.t the demo mode lock too as the magic bytes are below 8000 which means they should always be left alone.

This is excellent news as it means we can probably just use their bootloader like we do on other units.

Ralim commented 3 years ago

Yeah I'm getting around the right values for fridge and ambient with assuming same NTC as TS80P. Going to roll with that for now and just have to sort out the tip readings

g3gg0 commented 3 years ago

Did you spot where they are measuring the 90-110 ohms? (Sorry if ive missed it in the above).

one part: image

another part: image

and the source is the ADC5 code i posted in the last post with images (see PD1 toggling) image

g3gg0 commented 3 years ago

regarding the oddities: all C code you see is the result after using IDAs HexRays decompiler. the key is to name and prototype functions correctly (which is not always that easy). especially the _aeabi float and double functions are not that obvious to me, so it might be possible that an operation + - / or > < == might be swapped with its counterpart.

EDIT: just realized > and < were swapped :D fixed and updated the screenshots

g3gg0 commented 3 years ago

I'm thinking I need to trace out the ADC5 pin a bit better on this board to get an idea of what it is measuring.

edit: mixed ADC channels

to me it looks ADC0 measures the resistance of the heating element, resulting in 5.6 ohms.

ADC2 instead measures the resistor on the bottom side of the hotplate. from the looks the outer two of the three pins have an 100 ohms 0603 resistor in series with the temperature sensor which has 1.6905 ohms at 24.8°C. (yes, measured that accurate ;) )

g3gg0 commented 3 years ago

also realized that i probably mixed tempsens resistance and hotplate resistance. both get measured. but the hotplate is imho the one with 5.6 ohms.

g3gg0 commented 3 years ago

regarding heater resistance: this value is determined by toggling PA4, measuring ADC#0 when the IO is set, and measuring when its cleared. then it does this calculation: plate_heater_res = ((adc0_value_PA4_set - adc0_value_PA4_cleared) * 3300.0) * 1.6 / 1603993.6 / 0.45; this value is averaged 5 times and used as "hotplate resistance" which gets displayed in the info screen with e.g. "R:5.6"

regarding coding/temperature resistance: here the code sets PD1, reads ADC#5, clears PD1, reads ADC5 and does: plate_sensor_res = ((adc5_value_PD1_set - adc5_value_PD1_cleared) / (adc5_value_PD1_cleared + 4096 - adc5_value_PD1_set)) * 1000.0;

regarding hotplate temperature that resistance value is used along with ADC2 and ADC9 values: temperature = adc9_lut + ((5280.0 * adc2_avg) / 1112473.6 - (plate_sensor_res + 300.0) * (3300.0 - (5280.0 * adc2_avg) / 1112473.6) / 1000000.0) * 24.298 + 1.45;

regarding VUSB the code samples ADC#1 and does: vusb = adc1 * 3.3 * 110.0 / 40960.0 to get the USB voltage in 10mV resolution.

g3gg0 commented 3 years ago

ok found out why IOs are accessible via addresses like "0x42210190".

this is called bit banding and it not really well documented in the TRM. it seems the SFR bitbanding range starts at 0x42000000. if you want to directly set/clear a bit in 0x4001080C, then you use the offset 0x1080C 0x20 + bitnum 4 and add this to bitband base for SFRs 0x42000000. the result would be 0x42210180 for e.g. PA0 where you can write 0x00000000 or 0x00000001 to clear/set the bit.

so the above 0x42210190 toggled for ADC0 resolves to PA4

=> updated PA3, PA4, D0, D1 in the IO usage table

Ralim commented 3 years ago

@g3gg0

After reading your notes I've spent the time (hours) to trace out the PCB.

I think this explains a lot of what was slightly confusing by this:

There are two temperature sensors in the heater element.

There is the dedicated thermocouple on the 3 row of pins and there is also the normal inline one like the TS100/TS80 tips etc have.

image

image

For the first version of the firmware I'm inclined to just use the non-tip-inline sensor and see how well that works. I believe from your notes this is also what they are doing so that makes sense to me.

Thank you so much for the reverse engineering of the code ^

I'm going to integrate those equations to the code and test :) Will have more news when I have more time ❤️

Ralim commented 3 years ago

IDAs HexRays decompiler.

I wish i had a licence to use it, Its very powerful. I spent a few hours in Ghidra but didnt make much headway so went back to multimeter + patience. 🤣