// board enforces
// in-state
// accel set/resume
// out-state
// cancel button
// regen paddle
// accel rising edge
// brake rising edge
// brake > 0mph
// gm_: poor man's namespacing
int gm_brake_prev = 0 ;
int gm_gas_prev = 0 ;
int gm_speed = 0 ;
// silence everything if stock ECUs are still online
int gm_ascm_detected = 0 ;
int gm_ignition_started = 0 ;
static void gm_rx_hook ( CAN_FIFOMailBox_TypeDef * to_push ) {
int bus_number = ( to_push - > RDTR > > 4 ) & 0xFF ;
uint32_t addr ;
if ( to_push - > RIR & 4 ) {
// Extended
// Not looked at, but have to be separated
// to avoid address collision
addr = to_push - > RIR > > 3 ;
} else {
// Normal
addr = to_push - > RIR > > 21 ;
}
if ( addr = = 0x135 & & bus_number = = 0 ) {
//Gear selector (used for determining ignition)
int gear = to_push - > RDLR & 0x7 ;
gm_ignition_started = gear > 0 ; //Park = 0. If out of park, we're "on."
}
// sample speed, really only care if car is moving or not
// rear left wheel speed
if ( addr = = 842 ) {
gm_speed = to_push - > RDLR & 0xFFFF ;
}
// check if stock ASCM ECU is still online
if ( bus_number = = 0 & & addr = = 715 ) {
gm_ascm_detected = 1 ;
controls_allowed = 0 ;
}
// ACC steering wheel buttons
if ( addr = = 481 ) {
int buttons = ( to_push - > RDHR > > 12 ) & 0x7 ;
// res/set - enable, cancel button - disable
if ( buttons = = 2 | | buttons = = 3 ) {
controls_allowed = 1 ;
} else if ( buttons = = 6 ) {
controls_allowed = 0 ;
}
}
// exit controls on rising edge of brake press or on brake press when
// speed > 0
if ( addr = = 241 ) {
int brake = ( to_push - > RDLR & 0xFF00 ) > > 8 ;
// Brake pedal's potentiometer returns near-zero reading
// even when pedal is not pressed
if ( brake < 10 ) {
brake = 0 ;
}
if ( brake & & ( ! gm_brake_prev | | gm_speed ) ) {
controls_allowed = 0 ;
}
gm_brake_prev = brake ;
}
// exit controls on rising edge of gas press
if ( addr = = 417 ) {
int gas = to_push - > RDHR & 0xFF0000 ;
if ( gas & & ! gm_gas_prev ) {
controls_allowed = 0 ;
}
gm_gas_prev = gas ;
}
// exit controls on regen paddle
if ( addr = = 189 ) {
int regen = to_push - > RDLR & 0x20 ;
if ( regen ) {
controls_allowed = 0 ;
}
}
}
// all commands: gas/regen, friction 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 gm_tx_hook ( CAN_FIFOMailBox_TypeDef * to_send ) {
// There can be only one! (ASCM)
if ( gm_ascm_detected ) {
return 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 = gm_gas_prev | | ( gm_brake_prev & & gm_speed ) ;
int current_controls_allowed = controls_allowed & & ! pedal_pressed ;
uint32_t addr ;
if ( to_send - > RIR & 4 ) {
// Extended
addr = to_send - > RIR > > 3 ;
} else {
// Normal
addr = to_send - > RIR > > 21 ;
}
// BRAKE: safety check
if ( addr = = 789 ) {
int rdlr = to_send - > RDLR ;
int brake = ( ( rdlr & 0xF ) < < 8 ) + ( ( rdlr & 0xFF00 ) > > 8 ) ;
brake = ( 0x1000 - brake ) & 0xFFF ;
if ( current_controls_allowed ) {
if ( brake > 255 ) return 0 ;
} else {
if ( brake ! = 0 ) return 0 ;
}
}
// LKA STEER: safety check
if ( addr = = 384 ) {
int rdlr = to_send - > RDLR ;
int steer = ( ( rdlr & 0x7 ) < < 8 ) + ( ( rdlr & 0xFF00 ) > > 8 ) ;
int max_steer = 255 ;
if ( current_controls_allowed ) {
// Signed arithmetic
if ( steer & 0x400 ) {
if ( steer < ( 0x800 - max_steer ) ) return 0 ;
} else {
if ( steer > max_steer ) return 0 ;
}
} else {
if ( steer ! = 0 ) return 0 ;
}
}
// PARK ASSIST STEER: unlimited torque, no thanks
if ( addr = = 823 ) return 0 ;
// GAS/REGEN: safety check
if ( addr = = 715 ) {
int rdlr = to_send - > RDLR ;
int gas_regen = ( ( rdlr & 0x7F0000 ) > > 11 ) + ( ( rdlr & 0xF8000000 ) > > 27 ) ;
int apply = rdlr & 1 ;
if ( current_controls_allowed ) {
if ( gas_regen > 3072 ) return 0 ;
} else {
// Disabled message is !engaed with gas
// value that corresponds to max regen.
if ( apply | | gas_regen ! = 1404 ) return 0 ;
}
}
// 1 allows the message through
return true ;
}
static int gm_tx_lin_hook ( int lin_num , uint8_t * data , int len ) {
// LIN is not used in Volt
return false ;
}
static void gm_init ( int16_t param ) {
controls_allowed = 0 ;
gm_ignition_started = 0 ;
}
static int gm_ign_hook ( ) {
return gm_ignition_started ;
}
static int gm_fwd_hook ( int bus_num , CAN_FIFOMailBox_TypeDef * to_fwd ) {
return - 1 ;
}
const safety_hooks gm_hooks = {
. init = gm_init ,
. rx = gm_rx_hook ,
. tx = gm_tx_hook ,
. tx_lin = gm_tx_lin_hook ,
. ignition = gm_ign_hook ,
. fwd = gm_fwd_hook ,
} ;