@@ -8,7 +8,9 @@ const int VOLKSWAGEN_DRIVER_TORQUE_ALLOWANCE = 80;
8
8
const int VOLKSWAGEN_DRIVER_TORQUE_FACTOR = 3 ;
9
9
10
10
// Safety-relevant CAN messages for the Volkswagen MQB platform
11
+ #define MSG_ESP_19 0x0B2 // RX from ABS, for wheel speeds
11
12
#define MSG_EPS_01 0x09F // RX from EPS, for driver steering torque
13
+ #define MSG_ESP_05 0x106 // RX from ABS, for brake switch state
12
14
#define MSG_MOTOR_20 0x121 // RX from ECU, for driver throttle input
13
15
#define MSG_ACC_06 0x122 // RX from ACC radar, for status and engagement
14
16
#define MSG_HCA_01 0x126 // TX by OP, Heading Control Assist steering torque
@@ -19,11 +21,12 @@ const int VOLKSWAGEN_DRIVER_TORQUE_FACTOR = 3;
19
21
const AddrBus VOLKSWAGEN_MQB_TX_MSGS [] = {{MSG_HCA_01 , 0 }, {MSG_GRA_ACC_01 , 0 }, {MSG_GRA_ACC_01 , 2 }, {MSG_LDW_02 , 0 }};
20
22
const int VOLKSWAGEN_MQB_TX_MSGS_LEN = sizeof (VOLKSWAGEN_MQB_TX_MSGS ) / sizeof (VOLKSWAGEN_MQB_TX_MSGS [0 ]);
21
23
22
- // TODO: do checksum and counter checks
23
24
AddrCheckStruct volkswagen_mqb_rx_checks [] = {
24
- {.addr = {MSG_EPS_01 }, .bus = 0 , .expected_timestep = 10000U },
25
- {.addr = {MSG_ACC_06 }, .bus = 0 , .expected_timestep = 20000U },
26
- {.addr = {MSG_MOTOR_20 }, .bus = 0 , .expected_timestep = 20000U },
25
+ {.addr = {MSG_ESP_19 }, .bus = 0 , .check_checksum = false, .max_counter = 0U , .expected_timestep = 10000U },
26
+ {.addr = {MSG_EPS_01 }, .bus = 0 , .check_checksum = true, .max_counter = 15U , .expected_timestep = 10000U },
27
+ {.addr = {MSG_ESP_05 }, .bus = 0 , .check_checksum = true, .max_counter = 15U , .expected_timestep = 20000U },
28
+ {.addr = {MSG_MOTOR_20 }, .bus = 0 , .check_checksum = true, .max_counter = 15U , .expected_timestep = 20000U },
29
+ {.addr = {MSG_ACC_06 }, .bus = 0 , .check_checksum = true, .max_counter = 15U , .expected_timestep = 20000U },
27
30
};
28
31
const int VOLKSWAGEN_MQB_RX_CHECKS_LEN = sizeof (volkswagen_mqb_rx_checks ) / sizeof (volkswagen_mqb_rx_checks [0 ]);
29
32
@@ -32,9 +35,56 @@ struct sample_t volkswagen_torque_driver; // Last few driver torques measured
32
35
int volkswagen_rt_torque_last = 0 ;
33
36
int volkswagen_desired_torque_last = 0 ;
34
37
uint32_t volkswagen_ts_last = 0 ;
38
+ bool volkswagen_moving = false;
39
+ bool volkswagen_brake_pressed_prev = false;
35
40
int volkswagen_gas_prev = 0 ;
36
41
int volkswagen_torque_msg = 0 ;
37
42
int volkswagen_lane_msg = 0 ;
43
+ uint8_t volkswagen_crc8_lut_8h2f [256 ]; // Static lookup table for CRC8 poly 0x2F, aka 8H2F/AUTOSAR
44
+
45
+
46
+ static uint8_t volkswagen_get_checksum (CAN_FIFOMailBox_TypeDef * to_push ) {
47
+ return (uint8_t )GET_BYTE (to_push , 0 );
48
+ }
49
+
50
+ static uint8_t volkswagen_get_counter (CAN_FIFOMailBox_TypeDef * to_push ) {
51
+ return (uint8_t )GET_BYTE (to_push , 1 ) & 0xFU ;
52
+ }
53
+
54
+ static uint8_t volkswagen_mqb_compute_crc (CAN_FIFOMailBox_TypeDef * to_push ) {
55
+ int addr = GET_ADDR (to_push );
56
+ int len = GET_LEN (to_push );
57
+
58
+ // This is CRC-8H2F/AUTOSAR with a twist. See the OpenDBC implementation
59
+ // of this algorithm for a version with explanatory comments.
60
+
61
+ uint8_t crc = 0xFFU ;
62
+ for (int i = 1 ; i < len ; i ++ ) {
63
+ crc ^= (uint8_t )GET_BYTE (to_push , i );
64
+ crc = volkswagen_crc8_lut_8h2f [crc ];
65
+ }
66
+
67
+ uint8_t counter = volkswagen_get_counter (to_push );
68
+ switch (addr ) {
69
+ case MSG_EPS_01 :
70
+ crc ^= (uint8_t []){0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 ,0xF5 }[counter ];
71
+ break ;
72
+ case MSG_ESP_05 :
73
+ crc ^= (uint8_t []){0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 ,0x07 }[counter ];
74
+ break ;
75
+ case MSG_MOTOR_20 :
76
+ crc ^= (uint8_t []){0xE9 ,0x65 ,0xAE ,0x6B ,0x7B ,0x35 ,0xE5 ,0x5F ,0x4E ,0xC7 ,0x86 ,0xA2 ,0xBB ,0xDD ,0xEB ,0xB4 }[counter ];
77
+ break ;
78
+ case MSG_ACC_06 :
79
+ crc ^= (uint8_t []){0x37 ,0x7D ,0xF3 ,0xA9 ,0x18 ,0x46 ,0x6D ,0x4D ,0x3D ,0x71 ,0x92 ,0x9C ,0xE5 ,0x32 ,0x10 ,0xB9 }[counter ];
80
+ break ;
81
+ default : // Undefined CAN message, CRC check expected to fail
82
+ break ;
83
+ }
84
+ crc = volkswagen_crc8_lut_8h2f [crc ];
85
+
86
+ return crc ^ 0xFFU ;
87
+ }
38
88
39
89
static void volkswagen_mqb_init (int16_t param ) {
40
90
UNUSED (param );
@@ -43,17 +93,29 @@ static void volkswagen_mqb_init(int16_t param) {
43
93
relay_malfunction = false;
44
94
volkswagen_torque_msg = MSG_HCA_01 ;
45
95
volkswagen_lane_msg = MSG_LDW_02 ;
96
+ gen_crc_lookup_table (0x2F , volkswagen_crc8_lut_8h2f );
46
97
}
47
98
48
99
static int volkswagen_mqb_rx_hook (CAN_FIFOMailBox_TypeDef * to_push ) {
49
100
50
101
bool valid = addr_safety_check (to_push , volkswagen_mqb_rx_checks , VOLKSWAGEN_MQB_RX_CHECKS_LEN ,
51
- NULL , NULL , NULL );
102
+ volkswagen_get_checksum , volkswagen_mqb_compute_crc , volkswagen_get_counter );
52
103
53
104
if (valid ) {
54
105
int bus = GET_BUS (to_push );
55
106
int addr = GET_ADDR (to_push );
56
107
108
+ // Update in-motion state by sampling front wheel speeds
109
+ // Signal: ESP_19.ESP_VL_Radgeschw_02 (front left) in scaled km/h
110
+ // Signal: ESP_19.ESP_VR_Radgeschw_02 (front right) in scaled km/h
111
+ if ((bus == 0 ) && (addr == MSG_ESP_19 )) {
112
+ int wheel_speed_fl = GET_BYTE (to_push , 4 ) | (GET_BYTE (to_push , 5 ) << 8 );
113
+ int wheel_speed_fr = GET_BYTE (to_push , 6 ) | (GET_BYTE (to_push , 7 ) << 8 );
114
+ // Check for average front speed in excess of 0.3m/s, 1.08km/h
115
+ // DBC speed scale 0.0075: 0.3m/s = 144, sum both wheels to compare
116
+ volkswagen_moving = (wheel_speed_fl + wheel_speed_fr ) > 288 ;
117
+ }
118
+
57
119
// Update driver input torque samples
58
120
// Signal: EPS_01.Driver_Strain (absolute torque)
59
121
// Signal: EPS_01.Driver_Strain_VZ (direction)
@@ -83,6 +145,16 @@ static int volkswagen_mqb_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
83
145
volkswagen_gas_prev = gas ;
84
146
}
85
147
148
+ // Exit controls on rising edge of brake press
149
+ // Signal: ESP_05.ESP_Fahrer_bremst
150
+ if ((bus == 0 ) && (addr == MSG_ESP_05 )) {
151
+ bool brake_pressed = (GET_BYTE (to_push , 3 ) & 0x4 ) >> 2 ;
152
+ if (brake_pressed && (!(volkswagen_brake_pressed_prev ) || volkswagen_moving )) {
153
+ controls_allowed = 0 ;
154
+ }
155
+ volkswagen_brake_pressed_prev = brake_pressed ;
156
+ }
157
+
86
158
// If there are HCA messages on bus 0 not sent by OP, there's a relay problem
87
159
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT ) && (bus == 0 ) && (addr == MSG_HCA_01 )) {
88
160
relay_malfunction = true;
0 commit comments