SPORT HMI for Audi: Difference between revisions
(11 intermediate revisions by the same user not shown) | |||
Line 20: | Line 20: | ||
public static int mib2_sport_hmi_kzbFile = 100; | 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 <code>isComponentAvailable((short)52, carFuncAdap)</code> simply checks if 52nd channel in <code>Car_Function_Adaptations_Gen2</code> section is set to <code>on</code>. And 52nd channel is... You know which one - <code>[LO]_menu_display_SportHMI</code>. | |||
== Sport and Sport Kombi classes == | == Sport and Sport Kombi classes == | ||
Line 34: | Line 45: | ||
case 600289: { | case 600289: { | ||
return CarScreenBag1.cARSPORTMAIN(this, n2); | return CarScreenBag1.cARSPORTMAIN(this, n2); | ||
This one returns name of the screen for diagnostic purposes | |||
case 600289: { | |||
return "CAR_SPORT_MAIN"; | |||
} | |||
And this one executes conditions | And this one executes conditions | ||
Line 81: | Line 97: | ||
* 602113 - Oil temperature | * 602113 - Oil temperature | ||
* 602114 - Boost pressure | * 602114 - Boost pressure | ||
* 602116 - | * 602116 - ''TODO'' | ||
* | * 602118 - ''TODO'' | ||
State machine class is also referring to the SportHMI: | State machine class is also referring to the SportHMI: | ||
Line 89: | Line 104: | ||
Meaning of the above would be "Sport Display was selected from the CAR menu Left Drawer". | Meaning of the above would be "Sport Display was selected from the CAR menu Left Drawer". | ||
* 602 - | * 601 - SPORT_POWER | ||
* 603 - | * 602 - SPORT_POWER_MAX | ||
* 605 - | * 603 - SPORT_POWER_CURRENT | ||
* 606 - | * 604 - SPORT_TORQUE | ||
* 608 - | * 605 - SPORT_TORQUE_MAX | ||
* 606 - SPORT_TORQUE_CURRENT | |||
* 607 - SPORT_OIL_TEMPERATURE | |||
* 608 - SPORT_AIR_PRESSURE | |||
== Why no Sport submenu in Car menu? == | == Why no Sport submenu in Car menu? == | ||
It looks like everything is there. All the programming logic, data pulls, GUI assets, inits... So why it is not working? | It looks like everything is there. All the programming logic, adaptation to activate, data pulls, GUI assets, inits... So why it is not working? | ||
One of my theories 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? | 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 | Maybe let's analyse how the MENU and CAR MENU structures looks like: | ||
* Car | * Car | ||
** Audi Drive Select | ** Audi Drive Select | ||
** | ** Charging (eTron) | ||
** Statistics (eTron) | |||
** | ** Vehicle Settings | ||
** | ** Drive Assist | ||
** | |||
** Air Condition | ** Air Condition | ||
** Service and Checks | ** Service and Checks | ||
Line 121: | Line 135: | ||
* ... | * ... | ||
By the first look, I can see some similarities to the <code>CarEvoMenuEntryStructure.java</code> 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 <code>updateMenuEntryVisibility()</code> that appears in other car submenu classes. Not only those top-level. All of them. Is this it? | |||
== Moment of Doubt == | |||
Had a chance to test-drive an Audi SQ7 (4M) and played a bit with the Drive Select functions. There are "off-road" and "allroad" modes which enable additional element - Tilt Angle Display (TAD). This new element is visible directly on the Drive Select screen, and not as a separate submenu in the CAR menu. | |||
So it got me wondering. What if the SportHMI is also just an additional widget that should be displayed on the Drive Select screen when "Sport" or "Race" mode is selected? If so, it would mean that this function might be controlled via Gateway with proper dataset. Or it's a separate submenu but still enabled with a gateway dataset? | |||
I need to look into the Charisma menu and TAD elements in LSH.JXE... | |||
private IMenuEntry[] buildMenuCharisma(LogChannel logChannel) { | |||
// (...) | |||
menuEntry8.setFunctionalStateValues(new int[]{4}); //LIFT | |||
menuEntry2.setFunctionalStateValues(new int[]{4}); //OFFROAD | |||
menuEntry10.setFunctionalStateValues(new int[]{4}); //LIFT OFFROAD | |||
menuEntry5.setFunctionalStateValues(new int[]{8}); //EFFICIENCY | |||
// (...) | |||
MenuEntry menuEntry11 = this.entryFactory.createMenuEntry(250, "CHARISMA_EFFICIENCY_BCME_ADD_INFO", 1898776832); | |||
MenuEntry menuEntry12 = this.entryFactory.createMenuEntry(252, "CHARISMA_EFFICIENCY_BCME_CONSUMPTION_BARGRAPH", 1613564160); | |||
MenuEntry menuEntry13 = this.entryFactory.createMenuEntry(251, "CHARISMA_EFFICIENCY_BCME_CONSUMER_LIST", 1915554048); | |||
menuEntry11.setChildren(new IMenuEntry[]{menuEntry12, menuEntry13}); | |||
MenuEntry menuEntry14 = this.entryFactory.createMenuEntry(326, "TAD_MAIN", 1999374592); | |||
MenuEntry menuEntry15 = this.entryFactory.createMenuEntry(328, "TAD_PITCH_ANGLE", 1965820160); | |||
MenuEntry menuEntry16 = this.entryFactory.createMenuEntry(327, "TAD_ROLL_ANGLE", 1982597376); | |||
menuEntry14.setChildren(new IMenuEntry[]{menuEntry15, menuEntry16}); | |||
return new IMenuEntry[]{menuEntry, menuEntry2, menuEntry3, menuEntry4, menuEntry5, menuEntry7, menuEntry6, menuEntry8, menuEntry10, menuEntry9}; | |||
} | |||
Nope! It looks like only Efficiency Mode and Lift/Offroad Modes have children elements. No SportHMI mentions here. And previously mentioned <code>LD_CAR_SEL_SPORTDISPLAY</code> was linked to left drawer, which means that the SportHMI needs to be present in the CAR menu. | |||
But there's a RACE Mode mentioned here and there. | |||
MenuEntry menuEntry9 = this.entryFactory.createMenuEntry(238, "CHARISMA_PROFILE_RACE", 305203456); | |||
public boolean isRacesport() { | |||
return this.racesport; | |||
} | |||
Maybe that's it? Maybe the RACE Charisma mode needs to be enabled from the SportHMI to be accessible? | |||
Just to be sure, I will check if there are some "RACE" references in the code. | |||
== Figuring out the missing function == | |||
//todo | |||
== Modifications == | == Modifications with custom data == | ||
//TODO | //TODO | ||
ideas: | ideas: |
Latest revision as of 17:44, 8 June 2025

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

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);
This one returns name of the screen for diagnostic purposes
case 600289: { return "CAR_SPORT_MAIN"; }
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
It looks like everything is there. All the programming logic, adaptation to activate, data pulls, GUI assets, inits... So why it is not working?
One of my theories 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?
Moment of Doubt
Had a chance to test-drive an Audi SQ7 (4M) and played a bit with the Drive Select functions. There are "off-road" and "allroad" modes which enable additional element - Tilt Angle Display (TAD). This new element is visible directly on the Drive Select screen, and not as a separate submenu in the CAR menu.
So it got me wondering. What if the SportHMI is also just an additional widget that should be displayed on the Drive Select screen when "Sport" or "Race" mode is selected? If so, it would mean that this function might be controlled via Gateway with proper dataset. Or it's a separate submenu but still enabled with a gateway dataset?
I need to look into the Charisma menu and TAD elements in LSH.JXE...
private IMenuEntry[] buildMenuCharisma(LogChannel logChannel) { // (...) menuEntry8.setFunctionalStateValues(new int[]{4}); //LIFT menuEntry2.setFunctionalStateValues(new int[]{4}); //OFFROAD menuEntry10.setFunctionalStateValues(new int[]{4}); //LIFT OFFROAD menuEntry5.setFunctionalStateValues(new int[]{8}); //EFFICIENCY // (...) MenuEntry menuEntry11 = this.entryFactory.createMenuEntry(250, "CHARISMA_EFFICIENCY_BCME_ADD_INFO", 1898776832); MenuEntry menuEntry12 = this.entryFactory.createMenuEntry(252, "CHARISMA_EFFICIENCY_BCME_CONSUMPTION_BARGRAPH", 1613564160); MenuEntry menuEntry13 = this.entryFactory.createMenuEntry(251, "CHARISMA_EFFICIENCY_BCME_CONSUMER_LIST", 1915554048); menuEntry11.setChildren(new IMenuEntry[]{menuEntry12, menuEntry13}); MenuEntry menuEntry14 = this.entryFactory.createMenuEntry(326, "TAD_MAIN", 1999374592); MenuEntry menuEntry15 = this.entryFactory.createMenuEntry(328, "TAD_PITCH_ANGLE", 1965820160); MenuEntry menuEntry16 = this.entryFactory.createMenuEntry(327, "TAD_ROLL_ANGLE", 1982597376); menuEntry14.setChildren(new IMenuEntry[]{menuEntry15, menuEntry16}); return new IMenuEntry[]{menuEntry, menuEntry2, menuEntry3, menuEntry4, menuEntry5, menuEntry7, menuEntry6, menuEntry8, menuEntry10, menuEntry9}; }
Nope! It looks like only Efficiency Mode and Lift/Offroad Modes have children elements. No SportHMI mentions here. And previously mentioned LD_CAR_SEL_SPORTDISPLAY
was linked to left drawer, which means that the SportHMI needs to be present in the CAR menu.
But there's a RACE Mode mentioned here and there.
MenuEntry menuEntry9 = this.entryFactory.createMenuEntry(238, "CHARISMA_PROFILE_RACE", 305203456);
public boolean isRacesport() { return this.racesport; }
Maybe that's it? Maybe the RACE Charisma mode needs to be enabled from the SportHMI to be accessible?
Just to be sure, I will check if there are some "RACE" references in the code.
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