From 1f237019e77d2a8ed36b6ab633b6b2a842388be2 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Fri, 19 Jun 2026 14:16:01 -0500 Subject: [PATCH] Byte You In The --- opendbc_repo/opendbc/car/gm/carcontroller.py | 12 ++++++ opendbc_repo/opendbc/car/gm/carstate.py | 23 ++++++----- opendbc_repo/opendbc/car/gm/gmcan.py | 19 ++++++++- .../car/gm/tests/test_carcontroller.py | 39 +++++++++++++++++++ opendbc_repo/opendbc/car/gm/tests/test_gm.py | 22 ++++++++++- .../opendbc/car/gm/tests/test_gmcan.py | 35 +++++++++++++++++ .../generator/gm/gm_global_a_powertrain.dbc | 11 ++++++ .../dbc/gm_global_a_powertrain_generated.dbc | 11 ++++++ .../dbc/gm_global_a_powertrain_volt.dbc | 11 ++++++ 9 files changed, 172 insertions(+), 11 deletions(-) diff --git a/opendbc_repo/opendbc/car/gm/carcontroller.py b/opendbc_repo/opendbc/car/gm/carcontroller.py index 3288e5bf0..f179512cd 100644 --- a/opendbc_repo/opendbc/car/gm/carcontroller.py +++ b/opendbc_repo/opendbc/car/gm/carcontroller.py @@ -246,6 +246,14 @@ def should_activate_auto_hold(hold_ready: bool, auto_hold_armed: bool, auto_hold ) +def should_neutralize_volt_long_on_driver_override(CP, gas_pressed: bool, brake_pressed: bool) -> bool: + return ( + CP.carFingerprint in AUTO_HOLD_VOLT_CARS and + not CP.enableGasInterceptorDEPRECATED and + (gas_pressed or brake_pressed) + ) + + def get_friction_brake_bus(CP): volt_gateway_alt_brake = ( CP.carFingerprint == CAR.CHEVROLET_VOLT and @@ -800,6 +808,10 @@ class CarController(CarControllerBase): self.apply_gas = self.params.INACTIVE_REGEN self.apply_brake = max(self.apply_brake, self.volt_one_pedal_brake) + if should_neutralize_volt_long_on_driver_override(self.CP, CS.out.gasPressed, CS.out.brakePressed): + self.apply_gas = self.params.MAX_ACC_REGEN + self.apply_brake = 0 + maneuver_sng_launch = self.longitudinal_maneuver_mode and self.is_volt if ( self.CP.enableGasInterceptorDEPRECATED and diff --git a/opendbc_repo/opendbc/car/gm/carstate.py b/opendbc_repo/opendbc/car/gm/carstate.py index 843b7746b..c376199a8 100644 --- a/opendbc_repo/opendbc/car/gm/carstate.py +++ b/opendbc_repo/opendbc/car/gm/carstate.py @@ -50,6 +50,13 @@ BOLT_CANCEL_BUTTON_CARS = BOLT_GEN1_CANCEL_PERSONALITY_CARS | { CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL, CAR.CHEVROLET_BOLT_CC_2022_2023, } +VOLT_LIKE_CARS = { + CAR.CHEVROLET_VOLT, + CAR.CHEVROLET_VOLT_2019, + CAR.CHEVROLET_VOLT_ASCM, + CAR.CHEVROLET_VOLT_CAMERA, + CAR.CHEVROLET_VOLT_CC, +} class CarState(CarStateBase): @@ -108,14 +115,7 @@ class CarState(CarStateBase): ret = structs.CarState() - volt_like = { - CAR.CHEVROLET_VOLT, - CAR.CHEVROLET_VOLT_2019, - CAR.CHEVROLET_VOLT_ASCM, - CAR.CHEVROLET_VOLT_CAMERA, - CAR.CHEVROLET_VOLT_CC, - } - kaofui_state_cars = volt_like | SDGM_CAR | ASCM_INT | { + kaofui_state_cars = VOLT_LIKE_CARS | SDGM_CAR | ASCM_INT | { CAR.CHEVROLET_BLAZER, CAR.CHEVROLET_MALIBU_SDGM, CAR.CHEVROLET_MALIBU_HYBRID_CC, @@ -275,7 +275,10 @@ class CarState(CarStateBase): ret.seatbeltUnlatched = pt_cp.vl["BCMDoorBeltStatus"]["LeftSeatBelt"] == 0 ret.leftBlinker = pt_cp.vl["BCMTurnSignals"]["TurnSignals"] == 1 ret.rightBlinker = pt_cp.vl["BCMTurnSignals"]["TurnSignals"] == 2 - ret.parkingBrake = pt_cp.vl["BCMGeneralPlatformStatus"]["ParkBrakeSwActive"] == 1 + if self.CP.carFingerprint in VOLT_LIKE_CARS: + ret.parkingBrake = pt_cp.vl["EPBStatus"]["EPBClosed"] == 1 + else: + ret.parkingBrake = pt_cp.vl["BCMGeneralPlatformStatus"]["ParkBrakeSwActive"] == 1 else: # 1 - open, 0 - closed ret.doorOpen = (cam_cp.vl["BCMDoorBeltStatus"]["FrontLeftDoor"] == 1 or @@ -460,6 +463,8 @@ class CarState(CarStateBase): ("BCMGeneralPlatformStatus", 10), ("ASCMSteeringButton", 33), ] + if CP.carFingerprint in VOLT_LIKE_CARS: + pt_messages.append(("EPBStatus", 20)) if CP.enableBsm: pt_messages.append(("BCMBlindSpotMonitor", 0)) diff --git a/opendbc_repo/opendbc/car/gm/gmcan.py b/opendbc_repo/opendbc/car/gm/gmcan.py index ab2fab317..3e8a511ca 100644 --- a/opendbc_repo/opendbc/car/gm/gmcan.py +++ b/opendbc_repo/opendbc/car/gm/gmcan.py @@ -115,14 +115,31 @@ def create_adas_keepalive(bus): return [CanData(0x409, dat, bus), CanData(0x40a, dat, bus)] -def create_gas_regen_command(packer, bus, throttle, idx, enabled, at_full_stop, include_always_one3=False, use_volt_layout=False): +def create_gas_regen_command(packer, bus, throttle, idx, enabled, at_full_stop, include_always_one3=False, + use_volt_layout=False, use_generated_layout=False): gas_regen_msg = packer.dbc.name_to_msg.get("ASCMGasRegenCmd") + has_generated_layout = gas_regen_msg is not None and "GasRegenAccType" in gas_regen_msg.sigs has_legacy_volt_layout = gas_regen_msg is not None and { "GasRegenCmdActiveInv", "GasRegenAlwaysOne", "GasRegenAlwaysOne2", }.issubset(gas_regen_msg.sigs) + if use_generated_layout and has_generated_layout: + values = { + "GasRegenCmdActive": enabled, + "RollingCounter": idx, + "GasRegenCmd": throttle, + "GasRegenFullStopActive": at_full_stop, + "GasRegenAccType": 1, + } + dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[1] + values["GasRegenChecksum"] = (((0xff - dat[1]) & 0xff) << 16) | \ + (((0xff - dat[2]) & 0xff) << 8) | \ + ((0x100 - dat[3] - idx) & 0xff) + + return packer.make_can_msg("ASCMGasRegenCmd", bus, values) + if use_volt_layout and has_legacy_volt_layout: values = { "GasRegenCmdActive": enabled, diff --git a/opendbc_repo/opendbc/car/gm/tests/test_carcontroller.py b/opendbc_repo/opendbc/car/gm/tests/test_carcontroller.py index 84441397c..0460ebb62 100644 --- a/opendbc_repo/opendbc/car/gm/tests/test_carcontroller.py +++ b/opendbc_repo/opendbc/car/gm/tests/test_carcontroller.py @@ -46,6 +46,7 @@ from opendbc.car.gm.carcontroller import ( shape_truck_positive_accel, should_activate_auto_hold, should_activate_volt_one_pedal, + should_neutralize_volt_long_on_driver_override, should_send_stock_long_cancel, should_spoof_dash_speed, should_spoof_ecm_cruise_status, @@ -465,6 +466,44 @@ def test_volt_one_pedal_requires_time_in_drive_before_arming(): ) +def test_volt_driver_override_neutralization_applies_on_stock_acc_path(): + assert should_neutralize_volt_long_on_driver_override( + SimpleNamespace( + carFingerprint=CAR.CHEVROLET_VOLT_ASCM, + enableGasInterceptorDEPRECATED=False, + ), + True, + False, + ) + assert should_neutralize_volt_long_on_driver_override( + SimpleNamespace( + carFingerprint=CAR.CHEVROLET_VOLT_CAMERA, + enableGasInterceptorDEPRECATED=False, + ), + False, + True, + ) + + +def test_volt_driver_override_neutralization_skips_pedal_and_non_volt_paths(): + assert not should_neutralize_volt_long_on_driver_override( + SimpleNamespace( + carFingerprint=CAR.CHEVROLET_VOLT_ASCM, + enableGasInterceptorDEPRECATED=True, + ), + True, + False, + ) + assert not should_neutralize_volt_long_on_driver_override( + SimpleNamespace( + carFingerprint=CAR.CHEVROLET_BOLT_CC_2018_2021, + enableGasInterceptorDEPRECATED=False, + ), + True, + False, + ) + + def test_friction_brake_mode_keeps_near_stop_disabled_for_regular_long_braking(): CP = SimpleNamespace(carFingerprint=CAR.CHEVROLET_VOLT_ASCM) diff --git a/opendbc_repo/opendbc/car/gm/tests/test_gm.py b/opendbc_repo/opendbc/car/gm/tests/test_gm.py index da31a018b..285f5a934 100644 --- a/opendbc_repo/opendbc/car/gm/tests/test_gm.py +++ b/opendbc_repo/opendbc/car/gm/tests/test_gm.py @@ -18,7 +18,7 @@ from opendbc.car.gm.carcontroller import ( import opendbc.car.gm.interface as gm_interface from opendbc.car.common.conversions import Conversions as CV from opendbc.car.gm.fingerprints import FINGERPRINTS -from opendbc.car.gm.values import CAMERA_ACC_CAR, CAR, CC_ONLY_CAR, DBC, GM_RX_OFFSET, CruiseButtons, GMFlags, GMSafetyFlags +from opendbc.car.gm.values import CAMERA_ACC_CAR, CAR, CC_ONLY_CAR, DBC, GM_RX_OFFSET, CanBus, CruiseButtons, GMFlags, GMSafetyFlags from opendbc.safety import ALTERNATIVE_EXPERIENCE from openpilot.common.params import Params @@ -242,6 +242,26 @@ class TestGMInterface: assert "AEBCmd" in cam_parser.vl assert cam_parser.message_states[aeb_addr].ignore_alive + def test_volt_parking_brake_uses_epb_closed_not_bcm_switch(self): + CarInterface = interfaces[CAR.CHEVROLET_VOLT_ASCM] + car_params = CarInterface.get_params(CAR.CHEVROLET_VOLT_ASCM, _empty_fingerprint(), [], alpha_long=False, is_release=False, + docs=False, starpilot_toggles=_test_starpilot_toggles()) + car_state = GMCarState(car_params, custom.StarPilotCarParams.new_message()) + can_parsers = GMCarState.get_can_parsers(car_params) + packer = CANPacker(DBC[car_params.carFingerprint][Bus.pt]) + + def update_pt(epb_closed: int, park_brake_sw_active: int): + can_parsers[Bus.pt].update([0, [ + packer.make_can_msg("EPBStatus", CanBus.POWERTRAIN, {"EPBClosed": epb_closed}), + packer.make_can_msg("BCMGeneralPlatformStatus", CanBus.POWERTRAIN, {"ParkBrakeSwActive": park_brake_sw_active}), + ]]) + ret, _ = car_state.update(can_parsers, _test_starpilot_toggles()) + return ret + + assert "EPBStatus" in can_parsers[Bus.pt].vl + assert not update_pt(epb_closed=0, park_brake_sw_active=1).parkingBrake + assert update_pt(epb_closed=1, park_brake_sw_active=0).parkingBrake + def test_bolt_gen2_pedal_cancel_remap_sets_alt_exp(self): CarInterface = interfaces[CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL] fingerprint = _empty_fingerprint() diff --git a/opendbc_repo/opendbc/car/gm/tests/test_gmcan.py b/opendbc_repo/opendbc/car/gm/tests/test_gmcan.py index 2e00c96fd..e069ae9ed 100644 --- a/opendbc_repo/opendbc/car/gm/tests/test_gmcan.py +++ b/opendbc_repo/opendbc/car/gm/tests/test_gmcan.py @@ -1,3 +1,5 @@ +from types import SimpleNamespace + from opendbc.can import CANPacker from opendbc.car.gm import gmcan from opendbc.car.gm.values import CAR, DBC @@ -26,6 +28,39 @@ class TestGMCan: assert dat[1] & 0x1 assert decoded == 8848 + def test_prndl2_command_matches_bolt_gen2_regen_paddle_spoof(self): + CP = SimpleNamespace(carFingerprint=CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL) + + addr, dat, bus = gmcan.create_prndl2_command(self.packer, 0, False, CP) + assert addr == 0x1F5 + assert bus == 0 + assert dat.hex() == "0c0c000600000100" + + addr, dat, bus = gmcan.create_prndl2_command(self.packer, 0, True, CP) + assert addr == 0x1F5 + assert bus == 0 + assert dat.hex() == "0c0c000500020100" + + def test_prndl2_command_matches_bolt_gen1_regen_paddle_spoof(self): + CP = SimpleNamespace(carFingerprint=CAR.CHEVROLET_BOLT_CC_2018_2021) + + addr, dat, bus = gmcan.create_prndl2_command(self.packer, 0, True, CP) + + assert addr == 0x1F5 + assert bus == 0 + assert dat.hex() == "0c0c000700020100" + + def test_regen_paddle_command_matches_bolt_spoof(self): + addr, dat, bus = gmcan.create_regen_paddle_command(self.packer, 0, False) + assert addr == 0xBD + assert bus == 0 + assert dat.hex() == "00000000000000" + + addr, dat, bus = gmcan.create_regen_paddle_command(self.packer, 0, True) + assert addr == 0xBD + assert bus == 0 + assert dat.hex() == "20000000000000" + def test_gas_regen_command_matches_starpilot_volt_2019(self): packer = CANPacker(DBC[CAR.CHEVROLET_VOLT_2019]["pt"]) diff --git a/opendbc_repo/opendbc/dbc/generator/gm/gm_global_a_powertrain.dbc b/opendbc_repo/opendbc/dbc/generator/gm/gm_global_a_powertrain.dbc index 6e8eec072..1d86fb362 100644 --- a/opendbc_repo/opendbc/dbc/generator/gm/gm_global_a_powertrain.dbc +++ b/opendbc_repo/opendbc/dbc/generator/gm/gm_global_a_powertrain.dbc @@ -62,6 +62,12 @@ VAL_TABLE_ HandsOffSWDetectionMode 2 "Failed" 1 "Enabled" 0 "Disabled" ; BO_ 189 EBCMRegenPaddle: 7 K17_EBCM SG_ RegenPaddle : 7|4@0+ (1,0) [0|0] "" NEO + SG_ Byte1 : 15|8@0+ (1,0) [0|255] "" NEO + SG_ Byte2 : 23|8@0+ (1,0) [0|255] "" NEO + SG_ Byte3 : 31|8@0+ (1,0) [0|255] "" NEO + SG_ Byte4 : 39|8@0+ (1,0) [0|255] "" NEO + SG_ Byte5 : 47|8@0+ (1,0) [0|255] "" NEO + SG_ Byte6 : 55|8@0+ (1,0) [0|255] "" NEO BO_ 190 ECMAcceleratorPos: 6 K20_ECM SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO @@ -174,9 +180,14 @@ BO_ 500 SportMode: 6 XXX SG_ SportMode : 15|1@0+ (1,0) [0|1] "" XXX BO_ 501 ECMPRDNL2: 8 K20_ECM + SG_ Byte0 : 7|8@0+ (1,0) [0|255] "" NEO + SG_ Byte1 : 15|8@0+ (1,0) [0|255] "" NEO + SG_ Byte2 : 23|8@0+ (1,0) [0|255] "" NEO SG_ TransmissionState : 48|4@1+ (1,0) [0|7] "" NEO SG_ PRNDL2 : 27|4@0+ (1,0) [0|255] "" NEO + SG_ Byte4 : 39|8@0+ (1,0) [0|255] "" NEO SG_ ManualMode : 41|1@0+ (1,0) [0|1] "" NEO + SG_ Byte7 : 63|8@0+ (1,0) [0|255] "" NEO BO_ 532 BRAKE_RELATED: 6 XXX SG_ UserBrakePressure : 0|9@0+ (1,0) [0|511] "" XXX diff --git a/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_generated.dbc b/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_generated.dbc index 7aea83fed..dccbd87c3 100644 --- a/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_generated.dbc +++ b/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_generated.dbc @@ -82,6 +82,12 @@ VAL_TABLE_ HandsOffSWDetectionMode 2 "Failed" 1 "Enabled" 0 "Disabled" ; BO_ 189 EBCMRegenPaddle: 7 K17_EBCM SG_ RegenPaddle : 7|4@0+ (1,0) [0|0] "" NEO + SG_ Byte1 : 15|8@0+ (1,0) [0|255] "" NEO + SG_ Byte2 : 23|8@0+ (1,0) [0|255] "" NEO + SG_ Byte3 : 31|8@0+ (1,0) [0|255] "" NEO + SG_ Byte4 : 39|8@0+ (1,0) [0|255] "" NEO + SG_ Byte5 : 47|8@0+ (1,0) [0|255] "" NEO + SG_ Byte6 : 55|8@0+ (1,0) [0|255] "" NEO BO_ 190 ECMAcceleratorPos: 6 K20_ECM SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO @@ -194,9 +200,14 @@ BO_ 500 SportMode: 6 XXX SG_ SportMode : 15|1@0+ (1,0) [0|1] "" XXX BO_ 501 ECMPRDNL2: 8 K20_ECM + SG_ Byte0 : 7|8@0+ (1,0) [0|255] "" NEO + SG_ Byte1 : 15|8@0+ (1,0) [0|255] "" NEO + SG_ Byte2 : 23|8@0+ (1,0) [0|255] "" NEO SG_ TransmissionState : 48|4@1+ (1,0) [0|7] "" NEO SG_ PRNDL2 : 27|4@0+ (1,0) [0|255] "" NEO + SG_ Byte4 : 39|8@0+ (1,0) [0|255] "" NEO SG_ ManualMode : 41|1@0+ (1,0) [0|1] "" NEO + SG_ Byte7 : 63|8@0+ (1,0) [0|255] "" NEO BO_ 532 BRAKE_RELATED: 6 XXX SG_ UserBrakePressure : 0|9@0+ (1,0) [0|511] "" XXX diff --git a/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_volt.dbc b/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_volt.dbc index 9361c7569..35610a022 100644 --- a/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_volt.dbc +++ b/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_volt.dbc @@ -82,6 +82,12 @@ VAL_TABLE_ HandsOffSWDetectionMode 2 "Failed" 1 "Enabled" 0 "Disabled" ; BO_ 189 EBCMRegenPaddle: 7 K17_EBCM SG_ RegenPaddle : 7|4@0+ (1,0) [0|0] "" NEO + SG_ Byte1 : 15|8@0+ (1,0) [0|255] "" NEO + SG_ Byte2 : 23|8@0+ (1,0) [0|255] "" NEO + SG_ Byte3 : 31|8@0+ (1,0) [0|255] "" NEO + SG_ Byte4 : 39|8@0+ (1,0) [0|255] "" NEO + SG_ Byte5 : 47|8@0+ (1,0) [0|255] "" NEO + SG_ Byte6 : 55|8@0+ (1,0) [0|255] "" NEO BO_ 190 ECMAcceleratorPos: 6 K20_ECM SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO @@ -192,9 +198,14 @@ BO_ 500 SportMode: 6 XXX SG_ SportMode : 15|1@0+ (1,0) [0|1] "" XXX BO_ 501 ECMPRDNL2: 8 K20_ECM + SG_ Byte0 : 7|8@0+ (1,0) [0|255] "" NEO + SG_ Byte1 : 15|8@0+ (1,0) [0|255] "" NEO + SG_ Byte2 : 23|8@0+ (1,0) [0|255] "" NEO SG_ TransmissionState : 48|4@1+ (1,0) [0|7] "" NEO SG_ PRNDL2 : 27|4@0+ (1,0) [0|255] "" NEO + SG_ Byte4 : 39|8@0+ (1,0) [0|255] "" NEO SG_ ManualMode : 41|1@0+ (1,0) [0|1] "" NEO + SG_ Byte7 : 63|8@0+ (1,0) [0|255] "" NEO BO_ 532 BRAKE_RELATED: 6 XXX SG_ UserBrakePressure : 0|9@0+ (1,0) [0|511] "" XXX