355 lines
12 KiB
C
355 lines
12 KiB
C
// board enforces
|
|
// in-state
|
|
// accel set/resume
|
|
// out-state
|
|
// cancel button
|
|
// accel rising edge
|
|
// brake rising edge
|
|
// brake > 0mph
|
|
const AddrBus HONDA_N_TX_MSGS[] = {{0xE4, 0}, {0x194, 0}, {0x1FA, 0}, {0x200, 0}, {0x30C, 0}, {0x33D, 0}};
|
|
const AddrBus HONDA_BG_TX_MSGS[] = {{0xE4, 2}, {0x296, 0}, {0x33D, 2}}; // Bosch Giraffe
|
|
const AddrBus HONDA_BH_TX_MSGS[] = {{0xE4, 0}, {0x296, 1}, {0x33D, 0}}; // Bosch Harness
|
|
const int HONDA_GAS_INTERCEPTOR_THRESHOLD = 328; // ratio between offset and gain from dbc file
|
|
|
|
// Nidec and Bosch giraffe have pt on bus 0
|
|
AddrCheckStruct honda_rx_checks[] = {
|
|
{.addr = {0x1A6, 0x296}, .bus = 0, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U},
|
|
{.addr = { 0x158}, .bus = 0, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
|
|
{.addr = { 0x17C}, .bus = 0, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
|
|
};
|
|
const int HONDA_RX_CHECKS_LEN = sizeof(honda_rx_checks) / sizeof(honda_rx_checks[0]);
|
|
|
|
// Bosch harness has pt on bus 1
|
|
AddrCheckStruct honda_bh_rx_checks[] = {
|
|
{.addr = {0x296}, .bus = 1, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U},
|
|
{.addr = {0x158}, .bus = 1, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
|
|
{.addr = {0x17C}, .bus = 1, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
|
|
};
|
|
const int HONDA_BH_RX_CHECKS_LEN = sizeof(honda_bh_rx_checks) / sizeof(honda_bh_rx_checks[0]);
|
|
|
|
int honda_brake = 0;
|
|
bool honda_moving = false;
|
|
bool honda_alt_brake_msg = false;
|
|
bool honda_fwd_brake = false;
|
|
enum {HONDA_N_HW, HONDA_BG_HW, HONDA_BH_HW} honda_hw = HONDA_N_HW;
|
|
|
|
|
|
static uint8_t honda_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
|
|
int checksum_byte = GET_LEN(to_push) - 1;
|
|
return (uint8_t)(GET_BYTE(to_push, checksum_byte)) & 0xFU;
|
|
}
|
|
|
|
static uint8_t honda_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
|
|
int len = GET_LEN(to_push);
|
|
uint8_t checksum = 0U;
|
|
unsigned int addr = GET_ADDR(to_push);
|
|
while (addr > 0U) {
|
|
checksum += (addr & 0xFU); addr >>= 4;
|
|
}
|
|
for (int j = 0; j < len; j++) {
|
|
uint8_t byte = GET_BYTE(to_push, j);
|
|
checksum += (byte & 0xFU) + (byte >> 4U);
|
|
if (j == (len - 1)) {
|
|
checksum -= (byte & 0xFU); // remove checksum in message
|
|
}
|
|
}
|
|
return (8U - checksum) & 0xFU;
|
|
}
|
|
|
|
static uint8_t honda_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
|
|
int counter_byte = GET_LEN(to_push) - 1;
|
|
return ((uint8_t)(GET_BYTE(to_push, counter_byte)) >> 4U) & 0x3U;
|
|
}
|
|
|
|
static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
|
|
|
bool valid;
|
|
if (honda_hw == HONDA_BH_HW) {
|
|
valid = addr_safety_check(to_push, honda_bh_rx_checks, HONDA_BH_RX_CHECKS_LEN,
|
|
honda_get_checksum, honda_compute_checksum, honda_get_counter);
|
|
} else {
|
|
valid = addr_safety_check(to_push, honda_rx_checks, HONDA_RX_CHECKS_LEN,
|
|
honda_get_checksum, honda_compute_checksum, honda_get_counter);
|
|
}
|
|
|
|
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
|
|
|
if (valid) {
|
|
int addr = GET_ADDR(to_push);
|
|
int len = GET_LEN(to_push);
|
|
int bus = GET_BUS(to_push);
|
|
|
|
// sample speed
|
|
if (addr == 0x158) {
|
|
// first 2 bytes
|
|
honda_moving = GET_BYTE(to_push, 0) | GET_BYTE(to_push, 1);
|
|
}
|
|
|
|
// state machine to enter and exit controls
|
|
// 0x1A6 for the ILX, 0x296 for the Civic Touring
|
|
if ((addr == 0x1A6) || (addr == 0x296)) {
|
|
int button = (GET_BYTE(to_push, 0) & 0xE0) >> 5;
|
|
switch (button) {
|
|
case 2: // cancel
|
|
controls_allowed = 0;
|
|
break;
|
|
case 3: // set
|
|
case 4: // resume
|
|
controls_allowed = 1;
|
|
break;
|
|
default:
|
|
break; // any other button is irrelevant
|
|
}
|
|
}
|
|
|
|
// user brake signal on 0x17C reports applied brake from computer brake on accord
|
|
// and crv, which prevents the usual brake safety from working correctly. these
|
|
// cars have a signal on 0x1BE which only detects user's brake being applied so
|
|
// in these cases, this is used instead.
|
|
// most hondas: 0x17C bit 53
|
|
// accord, crv: 0x1BE bit 4
|
|
// exit controls on rising edge of brake press or on brake press when speed > 0
|
|
bool is_user_brake_msg = honda_alt_brake_msg ? ((addr) == 0x1BE) : ((addr) == 0x17C);
|
|
if (is_user_brake_msg) {
|
|
bool brake_pressed = honda_alt_brake_msg ? (GET_BYTE((to_push), 0) & 0x10) : (GET_BYTE((to_push), 6) & 0x20);
|
|
if (brake_pressed && (!brake_pressed_prev || honda_moving)) {
|
|
controls_allowed = 0;
|
|
}
|
|
brake_pressed_prev = brake_pressed;
|
|
}
|
|
|
|
// exit controls on rising edge of gas press if interceptor (0x201 w/ len = 6)
|
|
// length check because bosch hardware also uses this id (0x201 w/ len = 8)
|
|
if ((addr == 0x201) && (len == 6)) {
|
|
gas_interceptor_detected = 1;
|
|
int gas_interceptor = GET_INTERCEPTOR(to_push);
|
|
if (!unsafe_allow_gas && (gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD) &&
|
|
(gas_interceptor_prev <= HONDA_GAS_INTERCEPTOR_THRESHOLD)) {
|
|
controls_allowed = 0;
|
|
}
|
|
gas_interceptor_prev = gas_interceptor;
|
|
}
|
|
|
|
// exit controls on rising edge of gas press if no interceptor
|
|
if (!gas_interceptor_detected) {
|
|
if (addr == 0x17C) {
|
|
bool gas_pressed = GET_BYTE(to_push, 0) != 0;
|
|
if (!unsafe_allow_gas && gas_pressed && !gas_pressed_prev) {
|
|
controls_allowed = 0;
|
|
}
|
|
gas_pressed_prev = gas_pressed;
|
|
}
|
|
}
|
|
|
|
// disable stock Honda AEB in unsafe mode
|
|
if ( !(unsafe_mode & UNSAFE_DISABLE_STOCK_AEB) ) {
|
|
if ((bus == 2) && (addr == 0x1FA)) {
|
|
bool honda_stock_aeb = GET_BYTE(to_push, 3) & 0x20;
|
|
int honda_stock_brake = (GET_BYTE(to_push, 0) << 2) + ((GET_BYTE(to_push, 1) >> 6) & 0x3);
|
|
|
|
// Forward AEB when stock braking is higher than openpilot braking
|
|
// only stop forwarding when AEB event is over
|
|
if (!honda_stock_aeb) {
|
|
honda_fwd_brake = false;
|
|
} else if (honda_stock_brake >= honda_brake) {
|
|
honda_fwd_brake = true;
|
|
} else {
|
|
// Leave Honda forward brake as is
|
|
}
|
|
}
|
|
}
|
|
|
|
// if steering controls messages are received on the destination bus, it's an indication
|
|
// that the relay might be malfunctioning
|
|
int bus_rdr_car = (honda_hw == HONDA_BH_HW) ? 0 : 2; // radar bus, car side
|
|
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && ((addr == 0xE4) || (addr == 0x194))) {
|
|
if (((honda_hw != HONDA_N_HW) && (bus == bus_rdr_car)) ||
|
|
((honda_hw == HONDA_N_HW) && (bus == 0))) {
|
|
relay_malfunction_set();
|
|
}
|
|
}
|
|
}
|
|
return valid;
|
|
}
|
|
|
|
// all commands: gas, brake and steering
|
|
// if controls_allowed and no pedals pressed
|
|
// allow all commands up to limit
|
|
// else
|
|
// block all commands that produce actuation
|
|
|
|
static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
|
|
|
int tx = 1;
|
|
int addr = GET_ADDR(to_send);
|
|
int bus = GET_BUS(to_send);
|
|
|
|
if (honda_hw == HONDA_BG_HW) {
|
|
tx = msg_allowed(addr, bus, HONDA_BG_TX_MSGS, sizeof(HONDA_BG_TX_MSGS)/sizeof(HONDA_BG_TX_MSGS[0]));
|
|
} else if (honda_hw == HONDA_BH_HW) {
|
|
tx = msg_allowed(addr, bus, HONDA_BH_TX_MSGS, sizeof(HONDA_BH_TX_MSGS)/sizeof(HONDA_BH_TX_MSGS[0]));
|
|
} else {
|
|
tx = msg_allowed(addr, bus, HONDA_N_TX_MSGS, sizeof(HONDA_N_TX_MSGS)/sizeof(HONDA_N_TX_MSGS[0]));
|
|
}
|
|
|
|
if (relay_malfunction) {
|
|
tx = 0;
|
|
}
|
|
|
|
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
|
|
// and the the latching controls_allowed flag is True
|
|
int pedal_pressed = brake_pressed_prev && honda_moving;
|
|
bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS;
|
|
if (!unsafe_allow_gas) {
|
|
pedal_pressed = pedal_pressed || gas_pressed_prev || (gas_interceptor_prev > HONDA_GAS_INTERCEPTOR_THRESHOLD);
|
|
}
|
|
bool current_controls_allowed = controls_allowed && !(pedal_pressed);
|
|
|
|
// BRAKE: safety check
|
|
if ((addr == 0x1FA) && (bus == 0)) {
|
|
honda_brake = (GET_BYTE(to_send, 0) << 2) + ((GET_BYTE(to_send, 1) >> 6) & 0x3);
|
|
if (!current_controls_allowed) {
|
|
if (honda_brake != 0) {
|
|
tx = 0;
|
|
}
|
|
}
|
|
if (honda_brake > 255) {
|
|
tx = 0;
|
|
}
|
|
if (honda_fwd_brake) {
|
|
tx = 0;
|
|
}
|
|
}
|
|
|
|
// STEER: safety check
|
|
if ((addr == 0xE4) || (addr == 0x194)) {
|
|
if (!current_controls_allowed) {
|
|
bool steer_applied = GET_BYTE(to_send, 0) | GET_BYTE(to_send, 1);
|
|
if (steer_applied) {
|
|
tx = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// GAS: safety check
|
|
if (addr == 0x200) {
|
|
if (!current_controls_allowed) {
|
|
if (GET_BYTE(to_send, 0) || GET_BYTE(to_send, 1)) {
|
|
tx = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// FORCE CANCEL: safety check only relevant when spamming the cancel button in Bosch HW
|
|
// ensuring that only the cancel button press is sent (VAL 2) when controls are off.
|
|
// This avoids unintended engagements while still allowing resume spam
|
|
int bus_pt = (honda_hw == HONDA_BH_HW)? 1 : 0;
|
|
if ((addr == 0x296) && !current_controls_allowed && (bus == bus_pt)) {
|
|
if (((GET_BYTE(to_send, 0) >> 5) & 0x7) != 2) {
|
|
tx = 0;
|
|
}
|
|
}
|
|
|
|
// 1 allows the message through
|
|
return tx;
|
|
}
|
|
|
|
static void honda_nidec_init(int16_t param) {
|
|
UNUSED(param);
|
|
controls_allowed = false;
|
|
relay_malfunction_reset();
|
|
honda_hw = HONDA_N_HW;
|
|
honda_alt_brake_msg = false;
|
|
}
|
|
|
|
static void honda_bosch_giraffe_init(int16_t param) {
|
|
controls_allowed = false;
|
|
relay_malfunction_reset();
|
|
honda_hw = HONDA_BG_HW;
|
|
// Checking for alternate brake override from safety parameter
|
|
honda_alt_brake_msg = (param == 1) ? true : false;
|
|
}
|
|
|
|
static void honda_bosch_harness_init(int16_t param) {
|
|
controls_allowed = false;
|
|
relay_malfunction_reset();
|
|
honda_hw = HONDA_BH_HW;
|
|
// Checking for alternate brake override from safety parameter
|
|
honda_alt_brake_msg = (param == 1) ? true : false;
|
|
}
|
|
|
|
static int honda_nidec_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
|
// fwd from car to camera. also fwd certain msgs from camera to car
|
|
// 0xE4 is steering on all cars except CRV and RDX, 0x194 for CRV and RDX,
|
|
// 0x1FA is brake control, 0x30C is acc hud, 0x33D is lkas hud,
|
|
int bus_fwd = -1;
|
|
|
|
if (!relay_malfunction) {
|
|
if (bus_num == 0) {
|
|
bus_fwd = 2;
|
|
}
|
|
if (bus_num == 2) {
|
|
// block stock lkas messages and stock acc messages (if OP is doing ACC)
|
|
int addr = GET_ADDR(to_fwd);
|
|
bool is_lkas_msg = (addr == 0xE4) || (addr == 0x194) || (addr == 0x33D);
|
|
bool is_acc_hud_msg = addr == 0x30C;
|
|
bool is_brake_msg = addr == 0x1FA;
|
|
bool block_fwd = is_lkas_msg || is_acc_hud_msg || (is_brake_msg && !honda_fwd_brake);
|
|
if (!block_fwd) {
|
|
bus_fwd = 0;
|
|
}
|
|
}
|
|
}
|
|
return bus_fwd;
|
|
}
|
|
|
|
static int honda_bosch_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
|
int bus_fwd = -1;
|
|
int bus_rdr_cam = (honda_hw == HONDA_BH_HW) ? 2 : 1; // radar bus, camera side
|
|
int bus_rdr_car = (honda_hw == HONDA_BH_HW) ? 0 : 2; // radar bus, car side
|
|
|
|
if (!relay_malfunction) {
|
|
if (bus_num == bus_rdr_car) {
|
|
bus_fwd = bus_rdr_cam;
|
|
}
|
|
if (bus_num == bus_rdr_cam) {
|
|
int addr = GET_ADDR(to_fwd);
|
|
int is_lkas_msg = (addr == 0xE4) || (addr == 0x33D);
|
|
if (!is_lkas_msg) {
|
|
bus_fwd = bus_rdr_car;
|
|
}
|
|
}
|
|
}
|
|
return bus_fwd;
|
|
}
|
|
|
|
const safety_hooks honda_nidec_hooks = {
|
|
.init = honda_nidec_init,
|
|
.rx = honda_rx_hook,
|
|
.tx = honda_tx_hook,
|
|
.tx_lin = nooutput_tx_lin_hook,
|
|
.fwd = honda_nidec_fwd_hook,
|
|
.addr_check = honda_rx_checks,
|
|
.addr_check_len = sizeof(honda_rx_checks) / sizeof(honda_rx_checks[0]),
|
|
};
|
|
|
|
const safety_hooks honda_bosch_giraffe_hooks = {
|
|
.init = honda_bosch_giraffe_init,
|
|
.rx = honda_rx_hook,
|
|
.tx = honda_tx_hook,
|
|
.tx_lin = nooutput_tx_lin_hook,
|
|
.fwd = honda_bosch_fwd_hook,
|
|
.addr_check = honda_rx_checks,
|
|
.addr_check_len = sizeof(honda_rx_checks) / sizeof(honda_rx_checks[0]),
|
|
};
|
|
|
|
const safety_hooks honda_bosch_harness_hooks = {
|
|
.init = honda_bosch_harness_init,
|
|
.rx = honda_rx_hook,
|
|
.tx = honda_tx_hook,
|
|
.tx_lin = nooutput_tx_lin_hook,
|
|
.fwd = honda_bosch_fwd_hook,
|
|
.addr_check = honda_bh_rx_checks,
|
|
.addr_check_len = sizeof(honda_bh_rx_checks) / sizeof(honda_bh_rx_checks[0]),
|
|
};
|