// board enforces // in-state // accel set/resume // out-state // cancel button // accel rising edge // brake rising edge // brake > 0mph int ford_brake_prev = 0; int ford_gas_prev = 0; bool ford_moving = false; static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { int addr = GET_ADDR(to_push); if (addr == 0x217) { // wheel speeds are 14 bits every 16 ford_moving = false; for (int i = 0; i < 8; i += 2) { ford_moving |= GET_BYTE(to_push, i) | (GET_BYTE(to_push, (int)(i + 1)) & 0xFCU); } } // state machine to enter and exit controls if (addr == 0x83) { bool cancel = GET_BYTE(to_push, 1) & 0x1; bool set_or_resume = GET_BYTE(to_push, 3) & 0x30; if (cancel) { controls_allowed = 0; } if (set_or_resume) { controls_allowed = 1; } } // exit controls on rising edge of brake press or on brake press when // speed > 0 if (addr == 0x165) { int brake = GET_BYTE(to_push, 0) & 0x20; if (brake && (!(ford_brake_prev) || ford_moving)) { controls_allowed = 0; } ford_brake_prev = brake; } // exit controls on rising edge of gas press if (addr == 0x204) { int gas = (GET_BYTE(to_push, 0) & 0x03) | GET_BYTE(to_push, 1); if (gas && !(ford_gas_prev)) { controls_allowed = 0; } ford_gas_prev = gas; } } // all commands: just steering // if controls_allowed and no pedals pressed // allow all commands up to limit // else // block all commands that produce actuation static int ford_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int tx = 1; // disallow actuator commands if gas or brake (with vehicle moving) are pressed // and the the latching controls_allowed flag is True int pedal_pressed = ford_gas_prev || (ford_brake_prev && ford_moving); bool current_controls_allowed = controls_allowed && !(pedal_pressed); int addr = GET_ADDR(to_send); // STEER: safety check if (addr == 0x3CA) { if (!current_controls_allowed) { // bits 7-4 need to be 0xF to disallow lkas commands if ((GET_BYTE(to_send, 0) & 0xF0) != 0xF0) { tx = 0; } } } // FORCE CANCEL: safety check only relevant when spamming the cancel button // ensuring that set and resume aren't sent if (addr == 0x83) { if ((GET_BYTE(to_send, 3) & 0x30) != 0) { tx = 0; } } // 1 allows the message through return tx; } const safety_hooks ford_hooks = { .init = nooutput_init, .rx = ford_rx_hook, .tx = ford_tx_hook, .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = default_fwd_hook, };