diff --git a/common/libcommon.a b/common/libcommon.a index 8bd6bef5a3..d71cd76a2c 100644 Binary files a/common/libcommon.a and b/common/libcommon.a differ diff --git a/common/params_pyx.so b/common/params_pyx.so index 20b7da4032..ed9da73a21 100755 Binary files a/common/params_pyx.so and b/common/params_pyx.so differ diff --git a/opendbc_repo/opendbc/can/dbc.py b/opendbc_repo/opendbc/can/dbc.py index 5bc995059e..b5e5bf08f4 100644 --- a/opendbc_repo/opendbc/can/dbc.py +++ b/opendbc_repo/opendbc/can/dbc.py @@ -13,7 +13,7 @@ from opendbc.car.subaru.subarucan import subaru_checksum from opendbc.car.chrysler.chryslercan import chrysler_checksum, fca_giorgio_checksum from opendbc.car.hyundai.hyundaicanfd import hkg_can_fd_checksum from opendbc.car.volkswagen.mlbcan import volkswagen_mlb_checksum -from opendbc.car.volkswagen.mqbcan import volkswagen_mqb_meb_checksum, xor_checksum +from opendbc.car.volkswagen.mqbcan import volkswagen_meb_alt_crc_checksum, volkswagen_mqb_meb_checksum, xor_checksum from opendbc.car.tesla.teslacan import tesla_checksum from opendbc.car.body.bodycan import body_checksum from opendbc.car.psa.psacan import psa_checksum @@ -196,6 +196,8 @@ def get_checksum_state(dbc_name: str) -> ChecksumState | None: return ChecksumState(8, -1, 7, -1, False, SignalType.TOYOTA_CHECKSUM, toyota_checksum) elif dbc_name.startswith(("hyundai_canfd_generated", "hyundai_radar_210_21f_generated")): return ChecksumState(16, -1, 0, -1, True, SignalType.HKG_CAN_FD_CHECKSUM, hkg_can_fd_checksum) + elif dbc_name.startswith("vw_meb_2024"): + return ChecksumState(8, 4, 0, 0, True, SignalType.VOLKSWAGEN_MQB_MEB_CHECKSUM, volkswagen_meb_alt_crc_checksum) elif dbc_name.startswith(("vw_mqb", "vw_mqbevo", "vw_meb")): return ChecksumState(8, 4, 0, 0, True, SignalType.VOLKSWAGEN_MQB_MEB_CHECKSUM, volkswagen_mqb_meb_checksum) elif dbc_name.startswith("vw_mlb"): diff --git a/opendbc_repo/opendbc/car/volkswagen/mqbcan.py b/opendbc_repo/opendbc/car/volkswagen/mqbcan.py index fb370b3e2d..ebb1269b8b 100644 --- a/opendbc_repo/opendbc/car/volkswagen/mqbcan.py +++ b/opendbc_repo/opendbc/car/volkswagen/mqbcan.py @@ -185,6 +185,29 @@ def volkswagen_mqb_meb_checksum(address: int, sig, d: bytearray) -> int: return crc ^ 0xFF +def volkswagen_mqb_meb_dyn_len_checksum(address: int, sig, d: bytearray, length: int, const: list[int]) -> int: + d = d[:length] + crc = 0xFF + for i in range(1, len(d)): + crc ^= d[i] + crc = CRC8H2F[crc] + counter = d[1] & 0x0F + crc ^= const[counter] + crc = CRC8H2F[crc] + return crc ^ 0xFF + + +def volkswagen_meb_alt_crc_checksum(address: int, sig, d: bytearray) -> int: + entry = VOLKSWAGEN_MEB_ALT_CRC_CONSTANTS.get(address) + if entry: + length, const = entry + checksum = volkswagen_mqb_meb_dyn_len_checksum(address, sig, d, length, const) + if checksum == d[0]: + return checksum + + return volkswagen_mqb_meb_checksum(address, sig, d) + + def xor_checksum(address: int, sig, d: bytearray, initial_value: int = 0) -> int: checksum = initial_value checksum_byte = sig.start_bit // 8 @@ -258,3 +281,19 @@ VOLKSWAGEN_MQB_MEB_CONSTANTS: dict[int, list[int]] = { 0x65D: [0xAC, 0xB3, 0xAB, 0xEB, 0x7A, 0xE1, 0x3B, 0xF7, 0x73, 0xBA, 0x7C, 0x9E, 0x06, 0x5F, 0x02, 0xD9], # ESP_20 } + + +VOLKSWAGEN_MEB_ALT_CRC_CONSTANTS: dict[int, tuple[int, list[int]]] = { + 0x0DB: (42, [0x09, 0xFA, 0xCA, 0x8E, 0x62, 0xD5, 0xD1, 0xF0, + 0x31, 0xA0, 0xAF, 0xDA, 0x4D, 0x1A, 0x0A, 0x97]), # AWV_03 + 0xFC: (60, [0x69, 0xDC, 0xF9, 0x64, 0x6A, 0xCE, 0x55, 0x2C, + 0xC4, 0x38, 0x8F, 0xD1, 0xC6, 0x43, 0xB4, 0xB1]), # ESC_51 + 0x102: (44, [0xD7, 0x12, 0x85, 0x7E, 0x0B, 0x34, 0xFA, 0x16, + 0x7A, 0x25, 0x2D, 0x8F, 0x04, 0x8E, 0x5D, 0x35]), # ESC_50 + 0x10B: (44, [0x2C, 0xB1, 0x1A, 0x75, 0xBB, 0x65, 0x79, 0x47, + 0x81, 0x2B, 0xCC, 0x96, 0x17, 0xDB, 0xC0, 0x94]), # Motor_51 + 0x139: (28, [0x96, 0x92, 0x95, 0xB5, 0x6E, 0xE3, 0xBD, 0xB4, + 0xFA, 0xAE, 0xBE, 0xCB, 0xCF, 0xA5, 0x77, 0xEF]), # VMM_02 + 0x13D: (28, [0x18, 0x71, 0x10, 0x8D, 0xD7, 0xAA, 0xB0, 0x78, + 0xAC, 0x12, 0xAE, 0x0C, 0xDD, 0xF1, 0x85, 0x68]), # QFK_01 +} diff --git a/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py b/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py index 861210f143..028916dce6 100644 --- a/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py +++ b/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py @@ -8,7 +8,7 @@ from opendbc.car import Bus from opendbc.car.structs import CarParams from opendbc.car.volkswagen.interface import CarInterface from opendbc.car.volkswagen.fingerprints import FW_VERSIONS -from opendbc.car.volkswagen.mqbcan import volkswagen_mqb_meb_checksum +from opendbc.car.volkswagen.mqbcan import volkswagen_meb_alt_crc_checksum, volkswagen_mqb_meb_checksum from opendbc.car.volkswagen.radar_interface import RadarInterface from opendbc.car.volkswagen.values import CAR, DBC, FW_QUERY_CONFIG, WMI, CanBus, VolkswagenFlags, VolkswagenSafetyFlags @@ -75,6 +75,18 @@ class TestVolkswagenPlatformConfigs: data = bytearray.fromhex(data_hex) assert volkswagen_mqb_meb_checksum(0x25D, None, data) == data[0] + @pytest.mark.parametrize(("address", "data_hex"), ( + (0x0DB, "bb0ffcf0fefe0000fd0fffc0ff0000000200000000000000010000000000000000000000000000000000000000000000"), + (0x0FC, "650b1f007ef0b10c0000000000000000ffff1019191c1cfefe0000000000000000e0fff40140ffeb7f0748e481af421f00000000000000000000000000000000"), + (0x102, "9f0e7cfa010500000020cb0402000000b703a00000ec0f00000000002cd3ff1f0020a60000000020000000007d5256ab"), + (0x10B, "9d06000000007efe000000010000ff01feff000000000000000000000090240000000000000000000000000000000000"), + (0x139, "ac0e850b0890132000d019800000000000000000000000003002000500000000"), + (0x13D, "2412111101d1060000d0d410d106000000000000000000000000000000000000"), + )) + def test_meb_gen2_checksum(self, address, data_hex): + data = bytearray.fromhex(data_hex) + assert volkswagen_meb_alt_crc_checksum(address, None, data) == data[0] + def test_meb_camera_radar_tracks(self): cp = self._get_meb_params(CAR.SKODA_ENYAQ_MK1) radar = RadarInterface(cp) diff --git a/selfdrive/ui/onroad/exp_button.py b/selfdrive/ui/onroad/exp_button.py index f158881cd7..6e753551a1 100644 --- a/selfdrive/ui/onroad/exp_button.py +++ b/selfdrive/ui/onroad/exp_button.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import time import pyray as rl from openpilot.selfdrive.ui.ui_state import ui_state diff --git a/selfdrive/ui/tests/test_rivian_lateral_mode.py b/selfdrive/ui/tests/test_rivian_lateral_mode.py index 80e34435ef..e7042a4060 100644 --- a/selfdrive/ui/tests/test_rivian_lateral_mode.py +++ b/selfdrive/ui/tests/test_rivian_lateral_mode.py @@ -91,7 +91,7 @@ def load_lateral_mode(monkeypatch, *, brand="rivian", angle_harness=True, longit def load_exp_button(monkeypatch): draws = {"textures": [], "rings": []} fake_pyray = ModuleType("pyray") - fake_pyray.Color = FakeColor + fake_pyray.Color = lambda *args: FakeColor(*args) fake_pyray.Rectangle = FakeRectangle fake_pyray.Texture = FakeTexture fake_pyray.Vector2 = lambda x, y: SimpleNamespace(x=x, y=y) @@ -284,6 +284,7 @@ def test_inactive_lateral_is_not_classified(monkeypatch): def test_non_mici_wheel_icon_uses_rivian_tint(monkeypatch): module, draws = load_exp_button(monkeypatch) + assert not isinstance(module.rl.Color, type) button = module.ExpButton(192, 144) button.wheel_tint = FakeColor(0x4D, 0x9D, 0xFF, 255) button._update_state()