Keep Tesla screen lateral off until fresh engagement

This commit is contained in:
firestar5683
2026-11-02 08:11:23 -06:00
parent 97c6040a9f
commit 2ccc5fa9db
4 changed files with 70 additions and 3 deletions
@@ -110,7 +110,7 @@ static void tesla_screen_rx(const CANPacket_t *msg, bool autopark) {
const unsigned int state = (msg->data[1] >> 4U) & 7U;
const bool cruise = ((state == 2U) || (state == 3U) || (state == 4U) || (state == 6U) || (state == 7U)) && !tesla_screen_autopark;
const bool main_available = ((state == 1U) || cruise) && !tesla_screen_autopark;
if ((cruise && !tesla_screen_cruise) || (main_available && !tesla_screen_main)) {
if (cruise && !tesla_screen_cruise) {
tesla_screen_override = 0;
}
if (tesla_screen_main && !main_available && !brake_pressed) {
@@ -75,7 +75,7 @@ class TestTeslaScreenButton(unittest.TestCase):
self.touch(3)
self.assertEqual(self.permission(), 0)
def test_cruise_baseline_screen_override_and_main_cycle(self):
def test_cruise_baseline_screen_override_and_real_engagement(self):
self.feed(state=1)
self.assertEqual(self.permission(), 1)
self.touch(0)
@@ -88,8 +88,34 @@ class TestTeslaScreenButton(unittest.TestCase):
self.assertEqual(self.permission(), 0)
self.feed(state=0)
self.feed(state=1)
self.assertEqual(self.permission(), 0, 'availability is not a new driver engagement')
self.feed(state=2)
self.assertEqual(self.permission(), 1)
def test_availability_cycles_cannot_rearm_a_cleared_permission(self):
for word in (512, 1536):
for fault in ({'door': True}, {'eps': 3}, {'hands': 3}, {'gear': 0}):
with self.subTest(word=word, fault=fault):
self.start(word)
self.arm()
self.feed(state=1)
self.feed(state=1, **fault)
self.assertEqual(self.permission(), 0)
for state in (0, 1, 0, 1):
self.feed(state=state)
self.assertEqual(self.permission(), 0)
self.arm()
def test_brake_disengagement_cannot_be_undone_by_availability(self):
self.start(1536)
self.arm()
self.feed(state=1, brake=True)
self.assertEqual(self.permission(), 0)
for state in (0, 1, 0, 1):
self.feed(state=state)
self.assertEqual(self.permission(), 0)
self.arm()
def test_brake_word_and_physical_faults_withdraw(self):
for word in (512, 1536):
self.start(word)
@@ -22,7 +22,7 @@ class TeslaScreenCardIntent(AolCardIntent):
engaged = bool(CS.cruiseState.enabled)
available = bool(CS.cruiseState.available)
if (engaged and not self.previous_enabled) or (self.previous_available and not available and not CS.brakePressed):
self.screen_override = None
self.screen_override = None if engaged and not self.previous_enabled else False
self.brake_blocked = False
self.pause_lateral = False
cancel = any(event.type == ButtonType.cancel and event.pressed for event in CS.buttonEvents)
@@ -140,3 +140,44 @@ def test_screen_existing_intent_survives_known_gear_pause_without_new_arm(gear):
cs.gearShifter = 'drive'
owner.update(cs.as_reader(), now_ns=8, fault_active=False)
assert not owner.allowed_latch
@pytest.mark.parametrize('withdrawal', ['screen_off', 'can_timeout', 'native_rejection', 'cancel', 'brake'])
def test_availability_cycle_cannot_undo_an_explicit_or_fault_off(withdrawal):
owner = intent(brake=withdrawal == 'brake')
owner.update(state(available=False).as_reader(), now_ns=10)
owner.update(state(available=False, press=True).as_reader(), now_ns=20)
owner.update(state(available=True, press=False).as_reader(), now_ns=30)
assert owner.allowed_latch
cs = state()
kwargs = {}
if withdrawal == 'screen_off':
cs = state(press=True)
elif withdrawal == 'can_timeout':
cs.canTimeout = True
elif withdrawal == 'native_rejection':
kwargs['native_rejection_ns'] = 40
elif withdrawal == 'cancel':
cs.buttonEvents = [structs.CarState.ButtonEvent(type=ButtonType.cancel, pressed=True)]
else:
cs.brakePressed = True
owner.update(cs.as_reader(), now_ns=50, **kwargs)
assert not owner.allowed_latch
owner.update(state(press=False).as_reader(), now_ns=60)
for index, available in enumerate((False, True, False, True)):
owner.update(state(available=available).as_reader(), now_ns=70 + index)
assert not owner.allowed_latch
owner.update(state(press=True).as_reader(), now_ns=80)
assert owner.allowed_latch
def test_availability_off_still_allows_a_new_ordinary_cruise_engagement():
owner = intent()
owner.update(state().as_reader(), now_ns=10)
owner.update(state(press=True).as_reader(), now_ns=20)
assert not owner.allowed_latch
owner.update(state(available=False, press=False).as_reader(), now_ns=30)
owner.update(state(available=True).as_reader(), now_ns=40)
assert not owner.allowed_latch
owner.update(state(enabled=True).as_reader(), now_ns=50)
assert owner.allowed_latch and owner.screen_override is None