Announcement

Collapse
No announcement yet.

CSL '0401' Program Binary Disassembly Notes

Collapse
This is a sticky topic.
X
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • karter16
    replied
    Okay here's one for those who are concerned about heat-soak and the location of the IAT sensor.

    The CSL software has additional code in the function that calculates TAN (intake air temperature):

    Click image for larger version

Name:	Screenshot 2025-06-28 at 7.44.01 AM.png
Views:	652
Size:	127.9 KB
ID:	310119

    Lines 16 to 26 are not found in the standard euro software. These lines are calculating a version of TAN specifically for the purpose of being used in the CSL's calculation of air mass, which in turn is used in the calculation of final RF as we've seen previously.

    k_tan_m_cfg is set to 1 in the 0401 partial:

    Click image for larger version

Name:	Screenshot 2025-06-28 at 7.45.30 AM.png
Views:	877
Size:	4.3 KB
ID:	310120

    which means that tan_m is set from what I've tentatively named tan_m_adj.

    How is tan_m_adj calculated? Like this:

    Click image for larger version

Name:	Screenshot 2025-06-28 at 7.54.17 AM.png
Views:	632
Size:	169.8 KB
ID:	310121
    Click image for larger version

Name:	Screenshot 2025-06-28 at 7.54.49 AM.png
Views:	634
Size:	194.4 KB
ID:	310122
    Click image for larger version

Name:	Screenshot 2025-06-28 at 7.55.12 AM.png
Views:	621
Size:	206.0 KB
ID:	310123

    The key thing to understand about this function is that it is iterative. It runs every 100ms and the previous result is used to calculate the next.

    So what are the key behaviors?

    To simplify it down a lot, the function basically:

    1: Starts with IAT (measured intake temp)
    2: Compares it with TMOT (motor temp) and blends it to some degree based on:
    3: ML - load

    At high load tan_m_adj is pretty just TAN, at low load conditions where the engine is idling the tan_m_adj function is distrustful of what the IAT is telling it and calculates tan_m_adj more and more heavily based on tmot the longer the conditions continue.

    Why is this model needed? It is specifically to deal with heat-soak at idle and at stop conditions. The model prevents situations where the DME trusts the IAT in heat-soak scenarios. This would be bad as it would result in lean running conditions. The tan_m_adj model gives the DME a more realistic understanding of the actual intake temperature to ensure that lean conditions don't occur.

    It's a bit hard to graph, but this kind of shows the response of the model at various levels of load:


    Click image for larger version

Name:	Screenshot 2025-06-28 at 7.38.46 AM.png
Views:	623
Size:	182.5 KB
ID:	310124
    This isn't completely representative of how it works in reality as it is based on a fixed TAN reading, when in reality TAN will rise quickly due to heat soak, but what this graph does show is that at higher load levels the model heavily favors actual TAN (higher airflow = more accurate reading) at lower load levels it skews towards TMOT over time.

    I can't come up with a good way to graph or visually represent an actual scenario of a car coming to stop at the lights and the behavior of TAN and tan_m_adj, so you have to just work it through in your mind.

    Essentially this a fairly complex model which is tuned to handle IAT heat soak scenarios and give the air mass calculations a more accurate IAT value in those scenarios. The model is iterative and adjusts the tan_m_adj value further towards TMOT the longer the heat soak conditions continue.

    What's the lesson? Don't mess with your IAT sensor - the software is specifically calibrated to deal with heat soak conditions.

    Leave a comment:


  • terra
    replied
    Looks like a lot of work and knowledge developed here since I became less active. Very cool! I guess I know what my reading will be tonight

    Leave a comment:


  • Bry5on
    replied
    Originally posted by karter16 View Post

    Oh sorry! I completely missed that you already had that one - I wasn't meaning to be pedantic about the 7th decimal place lol
    Hahaha no stress. And I’m going to be taking this to 7 decimal places now. Because why not

    Leave a comment:


  • karter16
    replied
    Originally posted by Bry5on View Post

    well, close on relative opening
    Oh sorry! I completely missed that you already had that one - I wasn't meaning to be pedantic about the 7th decimal place lol

    Leave a comment:


  • karter16
    replied
    awesome! let me know tomorrow if there's anything else I can do to help figure those out :-)

    Leave a comment:


  • Bry5on
    replied
    Originally posted by karter16 View Post
    Okay - so all are served as per DS2 with the exception of TABG as you note.

    TAN (Intake Air Temp): correct - subtract 48
    TKA (Radiator Outlet Temp): correct - subtract 48
    TABG (Exhaust Gas Temp): correct - leave as is, DS2 divides by 16 to fit this into a byte instead of a word.
    AQ_REL (Relative Opening): multiply by 0.003051757
    LA_F_REGLER1 (Lambda Integrator 1): multiply by 0.000030517

    Let me know if this works :-)
    Beautiful. Thank you again my friend. Will test lambda integrator in the morning as it looks like I got the others sorted .. well, close on relative opening

    Leave a comment:


  • karter16
    replied
    Okay - so all are served as per DS2 with the exception of TABG as you note.

    TAN (Intake Air Temp): correct - subtract 48
    TKA (Radiator Outlet Temp): correct - subtract 48
    TABG (Exhaust Gas Temp): correct - leave as is, DS2 divides by 16 to fit this into a byte instead of a word.
    AQ_REL (Relative Opening): multiply by 0.003051757
    LA_F_REGLER1 (Lambda Integrator 1): multiply by 0.000030517

    Let me know if this works :-)

    Leave a comment:


  • karter16
    replied
    Originally posted by Bry5on View Post

    I'm so stoked too! Looks like it's outputting:
    Intake Air Temp and Radiator temp: subtract 48, just like DS2 message
    EGT: basically leave as-is, unlike DS2 message (multiply DS2 by 16)
    Relative Opening: not sure yet, some scalar that looks the same as DS2. DS2 multiply by .0030518
    Lambda Integrator: Subtract 2^15 then multiply by some factor that I'm not sure yet

    The fastest, easiest way to visualize, analyze, and share your automotive datalogs: for everyone from weekend hobbyists to pro tuners.


    Click image for larger version

Name:	Karterdatazaptest.png
Views:	280
Size:	158.5 KB
ID:	309366
    Awesome! I've got the config from TestO with the conversion factors so will dig those out shortly


    Sent from my iPhone using Tapatalk

    Leave a comment:


  • Bry5on
    replied
    Originally posted by karter16 View Post
    Yes! It is very satisfying to see that log!!! I'm so stoked that this has worked out!

    It's a good proof of the general approach for making such changes as well.


    Sent from my iPhone using Tapatalk
    I'm so stoked too! Looks like it's outputting:
    Intake Air Temp and Radiator temp: subtract 48, just like DS2 message
    EGT: basically leave as-is, unlike DS2 message (multiply DS2 by 16)
    Relative Opening: not sure yet, some scalar that looks the same as DS2. DS2 multiply by .0030518
    Lambda Integrator: Subtract 2^15 then multiply by some factor that I'm not sure yet

    The fastest, easiest way to visualize, analyze, and share your automotive datalogs: for everyone from weekend hobbyists to pro tuners.


    Click image for larger version

Name:	Karterdatazaptest.png
Views:	280
Size:	158.5 KB
ID:	309366

    Leave a comment:


  • karter16
    replied
    Yes! It is very satisfying to see that log!!! I'm so stoked that this has worked out!

    It's a good proof of the general approach for making such changes as well.


    Sent from my iPhone using Tapatalk

    Leave a comment:


  • Bry5on
    replied
    Originally posted by karter16 View Post
    I flashed the modified program to the DME this morning and good news, I didn't brick the DME. Even better news, I found the bug!

    As soon as I turned the ignition on after flashing I knew something was up as the DSC light was going mad. Modules relying on outbound CAN were throwing errors. It was a silly mistake to make that can be seen in the code above. I was trying to set the 17th frame in a 15 frame table..... 🤦‍♂️ Anyway, relocated the new CAN message to the unused 13th frame and refreshed. outbound CAN appears to now be working, all modules are error free and I used INPA to watch live CAN data coming in to the MK60 so the existing messages appear to be working without error.

    Without being setup to log CAN data that's as far as I can take it, so the binary is now with Bry5on to do some further testing when he gets the chance and to see if the new message is being transmitted and if there's good data on it.

    From there it will be a case of running with the modified program for a while and making sure that there isn't anything funny going on or any intermittent issues, etc. This is putting a small amount of additional load on the DME and is making the CAN bus busier, so we'll need to monitor and make sure there are no transient issues or less apparent bugs.

    Exciting progress though!
    My god the man has done it!! karter16 you are an absolute legend. Time to load this into the datalogger!
    Click image for larger version

Name:	KarterCANlog.png
Views:	159
Size:	292.3 KB
ID:	309355
    Click image for larger version

Name:	KarterCANlog2.png
Views:	154
Size:	285.2 KB
ID:	309356

    Leave a comment:


  • karter16
    replied
    I flashed the modified program to the DME this morning and good news, I didn't brick the DME. Even better news, I found the bug!

    As soon as I turned the ignition on after flashing I knew something was up as the DSC light was going mad. Modules relying on outbound CAN were throwing errors. It was a silly mistake to make that can be seen in the code above. I was trying to set the 17th frame in a 15 frame table..... 🤦‍♂️ Anyway, relocated the new CAN message to the unused 13th frame and refreshed. outbound CAN appears to now be working, all modules are error free and I used INPA to watch live CAN data coming in to the MK60 so the existing messages appear to be working without error.

    Without being setup to log CAN data that's as far as I can take it, so the binary is now with Bry5on to do some further testing when he gets the chance and to see if the new message is being transmitted and if there's good data on it.

    From there it will be a case of running with the modified program for a while and making sure that there isn't anything funny going on or any intermittent issues, etc. This is putting a small amount of additional load on the DME and is making the CAN bus busier, so we'll need to monitor and make sure there are no transient issues or less apparent bugs.

    Exciting progress though!

    Leave a comment:


  • liam821
    replied
    Originally posted by karter16 View Post
    I'm a bit concerned that I wrote the machine code for the new functions and haven't found any issues whatsoever with that work since. Usually that just means that you haven't found the bug yet 😏
    That's generally how I feel after I've spent all day coding a giant function and it compiles without issue the first time...suspicious...

    With that said, amazing work on decompiling the DME. This is very exciting work you're doing.

    Leave a comment:


  • Bry5on
    replied
    This is absolutely epic. Ready when you are my man! It’s been a while since I’ve done a regular full binary flash (as opposed to converting the bootloader). Fun!

    Leave a comment:


  • karter16
    replied
    Originally posted by heinzboehmer View Post

    I figured, but just double checking . Maybe throw a screenshot of that function up for code review completeness?

    C code LGTM. I looked through the assembly and it also seems fine, but my assembly skills are rusty, so take that with a grain of salt.
    sure thing - here we go :-). Note that CAN_send_frame() is the untouched original function that sends CAN frames to the bus.

    Click image for larger version  Name:	Screenshot 2025-06-20 at 2.11.34 PM.png Views:	0 Size:	52.9 KB ID:	309259

    Thanks! - I've validated it 3 different ways now

    1: This morning I went through the assembly by hand, confirming what it was doing and validating it against its sister functions. As part of this I made sure to track the before/after states of all registers, the stack, etc.
    2: I loaded the result in to Ghidra as you can see above and confirmed that both the disassembly and the C interpretation match what I expect.
    3: I asked ChatGPT to interpret and summarize the assembly to check that it's interpretation of what was going on matched my own.

    I'm at the point now where I can't really test it any further without loading it and giving it a go.

    To that end I've taken the exact program binary currently on my car, made the above modifications to it, done a before after comparison to make sure I didn't change anything else by accident and loaded it also into Ghidra to validate the assembly and C.

    Next up is to flash the program and try it out. As I mentioned I'm not setup for CAN logging, so will simply be validating that the DME, and car, runs without error. From that point on it'll be over to you and Bry5on to actually log the new message and confirm full functionality (if you're still game that is 😉)

    Also if there's anything else you want to see in more detail (existing CAN message functions, etc.) let me know!
    Last edited by karter16; 06-19-2025, 06:20 PM.

    Leave a comment:

Working...
X