#pragma once #include "opendbc/safety/safety_declarations.h" // Preglobal platform // 0x161 is ES_CruiseThrottle // 0x164 is ES_LKAS #define MSG_SUBARU_PG_CruiseControl 0x144U #define MSG_SUBARU_PG_Throttle 0x140U #define MSG_SUBARU_PG_Wheel_Speeds 0xD4U #define MSG_SUBARU_PG_Brake_Pedal 0xD1U #define MSG_SUBARU_PG_ES_LKAS 0x164U #define MSG_SUBARU_PG_ES_Distance 0x161U #define MSG_SUBARU_PG_Steering_Torque 0x371U #define SUBARU_PG_MAIN_BUS 0U #define SUBARU_PG_CAM_BUS 2U static bool subaru_pg_reversed_driver_torque = false; static void subaru_preglobal_rx_hook(const CANPacket_t *msg) { if (msg->bus == SUBARU_PG_MAIN_BUS) { if (msg->addr == MSG_SUBARU_PG_Steering_Torque) { int torque_driver_new; torque_driver_new = (msg->data[3] >> 5) + (msg->data[4] << 3); torque_driver_new = to_signed(torque_driver_new, 11); torque_driver_new = subaru_pg_reversed_driver_torque ? -torque_driver_new : torque_driver_new; update_sample(&torque_driver, torque_driver_new); } // enter controls on rising edge of ACC, exit controls on ACC off if (msg->addr == MSG_SUBARU_PG_CruiseControl) { bool cruise_engaged = (msg->data[6] >> 1) & 1U; pcm_cruise_check(cruise_engaged); } // update vehicle moving with any non-zero wheel speed if (msg->addr == MSG_SUBARU_PG_Wheel_Speeds) { vehicle_moving = ((GET_BYTES(msg, 0, 4) >> 12) != 0U) || (GET_BYTES(msg, 4, 4) != 0U); } if (msg->addr == MSG_SUBARU_PG_Brake_Pedal) { brake_pressed = ((GET_BYTES(msg, 0, 4) >> 16) & 0xFFU) > 0U; } if (msg->addr == MSG_SUBARU_PG_Throttle) { gas_pressed = msg->data[0] != 0U; } } } static bool subaru_preglobal_tx_hook(const CANPacket_t *msg) { const TorqueSteeringLimits SUBARU_PG_STEERING_LIMITS = { .max_torque = 2047, .max_rt_delta = 940, .max_rate_up = 50, .max_rate_down = 70, .driver_torque_multiplier = 10, .driver_torque_allowance = 75, .type = TorqueDriverLimited, }; bool tx = true; // steer cmd checks if (msg->addr == MSG_SUBARU_PG_ES_LKAS) { int desired_torque = ((GET_BYTES(msg, 0, 4) >> 8) & 0x1FFFU); desired_torque = -1 * to_signed(desired_torque, 13); bool steer_req = (msg->data[3] >> 0) & 1U; if (steer_torque_cmd_checks(desired_torque, steer_req, SUBARU_PG_STEERING_LIMITS)) { tx = false; } } return tx; } static safety_config subaru_preglobal_init(uint16_t param) { static const CanMsg SUBARU_PG_TX_MSGS[] = { {MSG_SUBARU_PG_ES_Distance, SUBARU_PG_MAIN_BUS, 8, .check_relay = true}, {MSG_SUBARU_PG_ES_LKAS, SUBARU_PG_MAIN_BUS, 8, .check_relay = true} }; // TODO: do checksum and counter checks after adding the signals to the outback dbc file static RxCheck subaru_preglobal_rx_checks[] = { {.msg = {{MSG_SUBARU_PG_Throttle, SUBARU_PG_MAIN_BUS, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, {.msg = {{MSG_SUBARU_PG_Steering_Torque, SUBARU_PG_MAIN_BUS, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, {.msg = {{MSG_SUBARU_PG_CruiseControl, SUBARU_PG_MAIN_BUS, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, {.msg = {{MSG_SUBARU_PG_Wheel_Speeds, SUBARU_PG_MAIN_BUS, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, {.msg = {{MSG_SUBARU_PG_Brake_Pedal, SUBARU_PG_MAIN_BUS, 4, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, }; const int SUBARU_PG_PARAM_REVERSED_DRIVER_TORQUE = 4; subaru_pg_reversed_driver_torque = GET_FLAG(param, SUBARU_PG_PARAM_REVERSED_DRIVER_TORQUE); return BUILD_SAFETY_CFG(subaru_preglobal_rx_checks, SUBARU_PG_TX_MSGS); } const safety_hooks subaru_preglobal_hooks = { .init = subaru_preglobal_init, .rx = subaru_preglobal_rx_hook, .tx = subaru_preglobal_tx_hook, };