SPORT HMI for Audi

From MIB-Helper.com Wiki
Revision as of 11:00, 15 February 2025 by Mr-fix (talk | contribs)
Jump to navigation Jump to search
Audi MMI MIB2 SportHMI mockup
Audi MMI SportHMI mockup

There are some indications of Sport_HMI app for Audi MIB2 firmware. But no-one yet have enabled it. Let's check methods from the VW/Skoda/Seat units and let's check how the LSD.JXE in Audi looks like when it comes to references to sport modes.

VW/SEAT/Skoda SportHMI enabling methods

For whatever reason, VW/SEAT/Skoda vehicles support SPORT HMI out from the factory, without some deep modifications of the system. All it needs is adaptation and FEC/SWaP code.

Details: SPORT HMI Performance Monitor

GUI assets in Audi firmware

Audi MIB2 MMI SportHMI GUI assets
Audi MIB2 MMI SportHMI GUI assets

There's a file SPORT_HMI.kzb - a .kzb package. After extracting, it looks like Audi firmware contains some GUI assets for Sport Display submenu. There's clock gauge for power and torque, as well as bar gauge for temperature and boost. Also rendered fonts for the large readouts inside the clock gauges.

So if we are looking for needed textures - all is here.

Here we can see that those textures are referenced in LSD.JXE classes:

public static String SPORT_HMI = "SPORT_HMI.kzb";
public static int mib2_sport_hmi_kzbFile = 100;

SportHMI adaptation channels

We all know that there are adaptation channels related to the Performance Monitor in VW, SEAT, and Skoda → http://wiki.mib-helper.com/index.php?title=SPORT_HMI_Performance_Monitor#Adaptation

And it looks like in Audi those are also connected to Sport Display function. Look at this part of code:

       if (this.isComponentAvailable((short)52, carFuncAdap)) {
           this.addCarComponent(new SportComponentEvo(this));
           this.addCarComponent(new SportKombiComponentEvo(this));
       }

The isComponentAvailable((short)52, carFuncAdap) simply checks if 52nd channel in Car_Function_Adaptations_Gen2 section is set to on. And 52nd channel is... You know which one - [LO]_menu_display_SportHMI.

Sport and Sport Kombi classes

It looks like there are two separate apps related to Sport Display feature:

  • SportHMI
  • SportHMI-Kombi

Kombi can be used to distinguish app version designed for instrument cluster ("Kombiinstrument")

Here's a statement that creates the screen:

protected Screen createScreen(int n, int n2) {
       switch (n) {
           (...)
           case 600289: {
               return CarScreenBag1.cARSPORTMAIN(this, n2);

And this one executes conditions

@Override
   public void executeCondition(int n, int n2, HMIView[] hMIViewArray, int n3) {
       switch (n2) {
       (...)              
           case 600289: {
               this.executeConditioncARSPORTMAINScreen(n, hMIViewArray, n3);
               break;
           }

...which look like this:

    private void executeConditioncARSPORTMAINScreen(int n, HMIView[] hMIViewArray, int n2) {
       switch (n) {
           case 601056: {
               if (hMIViewArray[0] == null) break;
               ((ScreenWidgetEVO)hMIViewArray[0]).setOpenSelectionDrawerByHkReturn(!this.evaluateSimpleChoiceModelValueEqualsCondition(-534050560, n2, -214497024));
               break;
           }
           case 602113: {
               if (hMIViewArray[0] != null) {
                   ((ContainerController)hMIViewArray[0]).setVisible(this.evaluateSimpleChoiceModelValueEqualsCondition(19925248, n2, 1));
               }
               if (hMIViewArray[1] == null) break;
               ((OilTemperatureGaugeController)hMIViewArray[1]).setVisible(this.evaluateSimpleChoiceModelValueEqualsCondition(19925248, n2, 1));
               break;
           }
           case 602114: {
               if (hMIViewArray[0] == null) break;
               ((ChargingAirPressureGaugeController)hMIViewArray[0]).setVisible(this.evaluateSimpleChoiceModelValueEqualsCondition(36702464, n2, 1));
               break;
           }
           case 602116: {
               if (hMIViewArray[0] == null) break;
               ((ContainerController)hMIViewArray[0]).setVisible(this.evaluateSimpleChoiceModelValueEqualsCondition(70256896, n2, 1));
               break;
           }
           case 602118: {
               if (hMIViewArray[0] == null) break;
               ((ContainerController)hMIViewArray[0]).setVisible(this.evaluateSimpleChoiceModelValueEqualsCondition(103811328, n2, 1));
               break;
           }
       }
   }

From the above:

  • 602113 - Oil temperature
  • 602114 - Boost pressure
  • 602116 - TODO
  • 602118 - TODO

State machine class is also referring to the SportHMI:

public static final int LD_CAR_SEL_SPORTDISPLAY;

Meaning of the above would be "Sport Display was selected from the CAR menu Left Drawer".

  • 601 - SPORT_POWER
  • 602 - SPORT_POWER_MAX
  • 603 - SPORT_POWER_CURRENT
  • 604 - SPORT_TORQUE
  • 605 - SPORT_TORQUE_MAX
  • 606 - SPORT_TORQUE_CURRENT
  • 607 - SPORT_OIL_TEMPERATURE
  • 608 - SPORT_AIR_PRESSURE

Why no Sport submenu in Car menu?

It looks like everything is there. All the programming logic, adaptation to activate, data pulls, GUI assets, inits... So why it is not working?

My theory is that at some point of development they decided to move the Sport HMI functionality from MIB to VC. On one side it makes sense - feature will not be duplicated on both displays. But on the other hand VC is optional equipment and not all cars have it.

For whatever reasons it was - they needed to remove Sport HMI from Audi MIB. And by "remove" I mean "make it not visible for user". That's why all the mentioned above parts of code and assets are there. So how they did it? And how to restore it?

Maybe let's analyse how the MENU and CAR MENU structures looks like:

  • Car
    • Audi Drive Select
    • Charging (eTron)
    • Statistics (eTron)
    • Vehicle Settings
    • Drive Assist
    • Air Condition
    • Service and Checks
    • Boardbook
  • Sound
  • Media
  • Phone
  • ...

By the first look, I can see some similarities to the CarEvoMenuEntryStructure.java class:

MenuEntry menuEntry2 = this.entryFactory.createMenuEntry(1596459264, "CAR_FUNC_CHARISMA", -282457856);
MenuEntry menuEntry3 = this.entryFactory.createMenuEntry(1630013696, "CAR_FUNC_SETTINGS", -1305802496);
MenuEntry menuEntry4 = this.entryFactory.createMenuEntry(1646790912, "CAR_FUNC_DRIVE_ASSIST", -1339356928);
MenuEntry menuEntry5 = this.entryFactory.createMenuEntry(1663568128, "CAR_FUNC_AIR_CONDITION", -1389688576);
MenuEntry menuEntry6 = this.entryFactory.createMenuEntry(1680345344, "CAR_FUNC_AUXHEAT", -1356134144);
MenuEntry menuEntry7 = this.entryFactory.createMenuEntry(10, "CAR_FUNC_AUX_AC)", -1372911360);
MenuEntry menuEntry8 = this.entryFactory.createMenuEntry(11, "CAR_FUNC_AUX_COMBINED)", 1210976512);
MenuEntry menuEntry9 = this.entryFactory.createMenuEntry(1713899776, "CAR_FUNC_SERVICE", -1322579712);
MenuEntry menuEntry10 = this.entryFactory.createMenuEntry(1177094400, "CAR_FUNC_BORDBOOK", 1412172032);
MenuEntry menuEntry11 = this.entryFactory.createMenuEntry(640289024, "CAR_FUNC_CHARGE", -1842607872);
MenuEntry menuEntry12 = this.entryFactory.createMenuEntry(-383121152, "CAR_FUNC_STATISTICS", -349370112);
MenuEntry menuEntry13 = this.entryFactory.createMenuEntry(12, "CAR_FUNC_SPORT", 120588544);

Now, let's check how the top-level menus are initialised and compare them to the SportHMI class to find what's missing. Maybe this will point us into the right direction.

After quick check and compare, it looks like there's one function missing from the SportComponentEvo class. It's updateMenuEntryVisibility() that appears in other car submenu classes. Not only those top-level. All of them. Is this it?

Figuring out the missing function

//todo

Modifications with custom data

//TODO ideas:

  • oil temp → gearbox temp
  • boost pressure → oil pressure
  • torque → steering angle
  • power → tachometer