Files
IQ.Pilot/iqdbc_repo/iqdbc/safety/modes/volkswagen_mqb.h
2026-07-21 13:43:46 -05:00

154 lines
5.8 KiB
C

#pragma once
#include "iqdbc/safety/declarations.h"
#include "iqdbc/safety/modes/volkswagen_common.h"
#define MSG_LWI_01 0x086U
#define MSG_MQB_APD_1 0x6A0U
#define MSG_MQB_DEBUG_LA 0x6A2U
static safety_config volkswagen_mqb_init(uint16_t param) {
static const CanMsg VOLKSWAGEN_MQB_STOCK_TX_MSGS[] = {{MSG_HCA_01, 0, 8, .check_relay = true}, {MSG_GRA_ACC_01, 0, 8, .check_relay = false}, {MSG_GRA_ACC_01, 2, 8, .check_relay = false},
{MSG_LDW_02, 0, 8, .check_relay = true}, {MSG_LH_EPS_03, 2, 8, .check_relay = true}, {MSG_MQB_APD_1, 1, 8, .check_relay = false}};
static const CanMsg VOLKSWAGEN_MQB_LONG_TX_MSGS[] = {{MSG_HCA_01, 0, 8, .check_relay = true}, {MSG_LDW_02, 0, 8, .check_relay = true}, {MSG_LH_EPS_03, 2, 8, .check_relay = true},
{MSG_ACC_02, 0, 8, .check_relay = true}, {MSG_ACC_06, 0, 8, .check_relay = true}, {MSG_ACC_07, 0, 8, .check_relay = true},
{MSG_MQB_APD_1, 1, 8, .check_relay = false}};
static RxCheck volkswagen_mqb_rx_checks[] = {
{.msg = {{MSG_ESP_19, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{MSG_LH_EPS_03, 0, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{MSG_ESP_05, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{MSG_TSK_06, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{MSG_MOTOR_20, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{MSG_MOTOR_14, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{MSG_GRA_ACC_01, 0, 8, 33U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}},
};
volkswagen_common_init();
#ifdef ALLOW_DEBUG
volkswagen_longitudinal = GET_FLAG(param, FLAG_VOLKSWAGEN_LONG_CONTROL);
volkswagen_allow_long_accel_with_gas_pressed = GET_FLAG(param, FLAG_VOLKSWAGEN_ALLOW_LONG_ACCEL_WITH_GAS_PRESSED);
#else
SAFETY_UNUSED(param);
#endif
return volkswagen_longitudinal ? BUILD_SAFETY_CFG(volkswagen_mqb_rx_checks, VOLKSWAGEN_MQB_LONG_TX_MSGS) : \
BUILD_SAFETY_CFG(volkswagen_mqb_rx_checks, VOLKSWAGEN_MQB_STOCK_TX_MSGS);
}
static void volkswagen_mqb_rx_hook(const CANPacket_t *msg) {
if (msg->bus == 0U) {
if (msg->addr == MSG_ESP_19) {
uint32_t speed = 0U;
for (uint8_t i = 0U; i < 8U; i += 2U) {
speed += (uint32_t)msg->data[i] | ((uint32_t)msg->data[i + 1U] << 8);
}
vehicle_moving = speed > 0U;
UPDATE_VEHICLE_SPEED(((float)speed / 4.0f) * 0.0075f / 3.6f);
}
if (msg->addr == MSG_LH_EPS_03) {
update_sample(&torque_driver, volkswagen_mlb_mqb_driver_input_torque(msg));
}
if (msg->addr == MSG_TSK_06) {
int acc_status = (msg->data[3] & 0x7U);
bool cruise_engaged = (acc_status == 3) || (acc_status == 4) || (acc_status == 5);
acc_main_on = cruise_engaged || (acc_status == 2);
if (!volkswagen_longitudinal) {
pcm_cruise_check(cruise_engaged);
}
if (!acc_main_on) {
controls_allowed = false;
}
}
if (msg->addr == MSG_GRA_ACC_01) {
if (volkswagen_longitudinal) {
bool set_button = GET_BIT(msg, 16U);
bool resume_button = GET_BIT(msg, 19U);
if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) {
controls_allowed = acc_main_on;
}
volkswagen_set_button_prev = set_button;
volkswagen_resume_button_prev = resume_button;
}
if (GET_BIT(msg, 13U)) {
controls_allowed = false;
}
}
if (msg->addr == MSG_MOTOR_20) {
gas_pressed = ((GET_BYTES(msg, 0, 4) >> 12) & 0xFFU) != 0U;
}
if (msg->addr == MSG_MOTOR_14) {
volkswagen_brake_pedal_switch = GET_BIT(msg, 28U);
}
if (msg->addr == MSG_ESP_05) {
volkswagen_brake_pressure_detected = GET_BIT(msg, 26U);
}
if (msg->addr == MSG_LWI_01) {
uint16_t lwi_angle_raw = ((uint16_t)msg->data[2] | ((uint16_t)msg->data[3] << 8)) & 0x1FFFU;
bool lwi_angle_sign = ((msg->data[3] >> 5) & 0x1U) != 0U;
float lwi_angle_deg = (float)lwi_angle_raw * 0.1f;
vw_iq_measured_angle_deg = lwi_angle_sign ? -lwi_angle_deg : lwi_angle_deg;
uint16_t alc_angle_raw = (uint16_t)msg->data[5] | ((uint16_t)msg->data[6] << 8);
vw_iq_alc_desired_angle_deg = (float)alc_angle_raw * 0.1f;
vw_iq_alc_active = msg->data[7] != 0U;
}
brake_pressed = volkswagen_brake_pedal_switch || volkswagen_brake_pressure_detected;
}
}
static bool volkswagen_mqb_tx_hook(const CANPacket_t *msg) {
bool tx = true;
if (msg->addr == MSG_MQB_APD_1) {
volkswagen_iq_decode_apd(msg);
}
if (msg->addr == MSG_HCA_01) {
volkswagen_iq_send_debug_la(MSG_MQB_DEBUG_LA, 1U);
}
if ((msg->addr == MSG_ACC_06) || (msg->addr == MSG_ACC_07)) {
int desired_accel = 0;
if (msg->addr == MSG_ACC_06) {
desired_accel = ((((msg->data[4] & 0x7U) << 8) | msg->data[3]) * 5U) - 7220U;
} else {
desired_accel = (((msg->data[7] << 3) | ((msg->data[6] & 0xE0U) >> 5)) * 5U) - 7220U;
}
if (volkswagen_iq_long_accel_check(desired_accel)) {
tx = false;
}
}
if ((msg->addr == MSG_GRA_ACC_01) && !controls_allowed) {
if ((msg->data[2] & 0x9U) != 0U) {
tx = false;
}
}
return tx;
}
const safety_hooks volkswagen_mqb_hooks = {
.init = volkswagen_mqb_init,
.rx = volkswagen_mqb_rx_hook,
.tx = volkswagen_mqb_tx_hook,
.get_counter = volkswagen_mqb_meb_get_counter,
.get_checksum = volkswagen_mqb_meb_get_checksum,
.compute_checksum = volkswagen_mqb_meb_compute_crc,
};