1
- // Safety-relevant CAN messages for the Volkswagen MQB platform.
2
- #define MSG_EPS_01 0x09F
3
- #define MSG_MOTOR_20 0x121
4
- #define MSG_ACC_06 0x122
5
- #define MSG_HCA_01 0x126
6
- #define MSG_GRA_ACC_01 0x12B
7
- #define MSG_LDW_02 0x397
8
-
1
+ // Safety-relevant steering constants for Volkswagen
9
2
const int VOLKSWAGEN_MAX_STEER = 250 ; // 2.5 Nm (EPS side max of 3.0Nm with fault if violated)
10
3
const int VOLKSWAGEN_MAX_RT_DELTA = 75 ; // 4 max rate up * 50Hz send rate * 250000 RT interval / 1000000 = 50 ; 50 * 1.5 for safety pad = 75
11
4
const uint32_t VOLKSWAGEN_RT_INTERVAL = 250000 ; // 250ms between real time checks
12
- const int VOLKSWAGEN_MAX_RATE_UP = 4 ; // 2.0 Nm/s available rate of change from the steering rack (EPS side delta -limit of 5.0 Nm/s)
13
- const int VOLKSWAGEN_MAX_RATE_DOWN = 10 ; // 5.0 Nm/s available rate of change from the steering rack (EPS side delta -limit of 5.0 Nm/s)
5
+ const int VOLKSWAGEN_MAX_RATE_UP = 4 ; // 2.0 Nm/s RoC limit (EPS rack has own soft -limit of 5.0 Nm/s)
6
+ const int VOLKSWAGEN_MAX_RATE_DOWN = 10 ; // 5.0 Nm/s RoC limit (EPS rack has own soft -limit of 5.0 Nm/s)
14
7
const int VOLKSWAGEN_DRIVER_TORQUE_ALLOWANCE = 80 ;
15
8
const int VOLKSWAGEN_DRIVER_TORQUE_FACTOR = 3 ;
16
9
17
- // MSG_GRA_ACC_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration
18
- const AddrBus VOLKSWAGEN_TX_MSGS [] = {{MSG_HCA_01 , 0 }, {MSG_GRA_ACC_01 , 0 }, {MSG_GRA_ACC_01 , 2 }, {MSG_LDW_02 , 0 }};
10
+ // Safety-relevant CAN messages for the Volkswagen MQB platform
11
+ #define MSG_EPS_01 0x09F // RX from EPS, for driver steering torque
12
+ #define MSG_MOTOR_20 0x121 // RX from ECU, for driver throttle input
13
+ #define MSG_ACC_06 0x122 // RX from ACC radar, for status and engagement
14
+ #define MSG_HCA_01 0x126 // TX by OP, Heading Control Assist steering torque
15
+ #define MSG_GRA_ACC_01 0x12B // TX by OP, ACC control buttons for cancel/resume
16
+ #define MSG_LDW_02 0x397 // TX by OP, Lane line recognition and text alerts
17
+
18
+ // Transmit of GRA_ACC_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration
19
+ 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
+ const int VOLKSWAGEN_MQB_TX_MSGS_LEN = sizeof (VOLKSWAGEN_MQB_TX_MSGS ) / sizeof (VOLKSWAGEN_MQB_TX_MSGS [0 ]);
19
21
20
22
// TODO: do checksum and counter checks
21
- AddrCheckStruct volkswagen_rx_checks [] = {
23
+ AddrCheckStruct volkswagen_mqb_rx_checks [] = {
22
24
{.addr = {MSG_EPS_01 }, .bus = 0 , .expected_timestep = 10000U },
23
25
{.addr = {MSG_ACC_06 }, .bus = 0 , .expected_timestep = 20000U },
24
26
{.addr = {MSG_MOTOR_20 }, .bus = 0 , .expected_timestep = 20000U },
25
27
};
28
+ const int VOLKSWAGEN_MQB_RX_CHECKS_LEN = sizeof (volkswagen_mqb_rx_checks ) / sizeof (volkswagen_mqb_rx_checks [0 ]);
26
29
27
- const int VOLKSWAGEN_RX_CHECK_LEN = sizeof (volkswagen_rx_checks ) / sizeof (volkswagen_rx_checks [0 ]);
28
30
29
- struct sample_t volkswagen_torque_driver ; // last few driver torques measured
31
+ struct sample_t volkswagen_torque_driver ; // Last few driver torques measured
30
32
int volkswagen_rt_torque_last = 0 ;
31
33
int volkswagen_desired_torque_last = 0 ;
32
34
uint32_t volkswagen_ts_last = 0 ;
33
35
int volkswagen_gas_prev = 0 ;
36
+ int volkswagen_torque_msg = 0 ;
37
+ int volkswagen_lane_msg = 0 ;
38
+
39
+ static void volkswagen_mqb_init (int16_t param ) {
40
+ UNUSED (param );
34
41
35
- static int volkswagen_rx_hook (CAN_FIFOMailBox_TypeDef * to_push ) {
42
+ controls_allowed = false;
43
+ relay_malfunction = false;
44
+ volkswagen_torque_msg = MSG_HCA_01 ;
45
+ volkswagen_lane_msg = MSG_LDW_02 ;
46
+ }
47
+
48
+ static int volkswagen_mqb_rx_hook (CAN_FIFOMailBox_TypeDef * to_push ) {
36
49
37
- bool valid = addr_safety_check (to_push , volkswagen_rx_checks , VOLKSWAGEN_RX_CHECK_LEN ,
50
+ bool valid = addr_safety_check (to_push , volkswagen_mqb_rx_checks , VOLKSWAGEN_MQB_RX_CHECKS_LEN ,
38
51
NULL , NULL , NULL );
39
52
40
53
if (valid ) {
41
- int bus = GET_BUS (to_push );
42
- int addr = GET_ADDR (to_push );
43
-
44
- // Update driver input torque samples from EPS_01.Driver_Strain for absolute torque, and EPS_01.Driver_Strain_VZ
45
- // for the direction.
46
- if ((bus == 0 ) && (addr == MSG_EPS_01 )) {
47
- int torque_driver_new = GET_BYTE (to_push , 5 ) | ((GET_BYTE (to_push , 6 ) & 0x1F ) << 8 );
48
- int sign = (GET_BYTE (to_push , 6 ) & 0x80 ) >> 7 ;
49
- if (sign == 1 ) {
50
- torque_driver_new *= -1 ;
51
- }
52
-
53
- update_sample (& volkswagen_torque_driver , torque_driver_new );
54
- }
55
-
56
- // Monitor ACC_06.ACC_Status_ACC for stock ACC status. Because the current MQB port is lateral-only, OP's control
57
- // allowed state is directly driven by stock ACC engagement. Permit the ACC message to come from either bus, in
58
- // order to accommodate future camera-side integrations if needed.
59
- if (addr == MSG_ACC_06 ) {
60
- int acc_status = (GET_BYTE (to_push , 7 ) & 0x70 ) >> 4 ;
61
- controls_allowed = ((acc_status == 3 ) || (acc_status == 4 ) || (acc_status == 5 )) ? 1 : 0 ;
62
- }
63
-
64
- // exit controls on rising edge of gas press. Bits [12-20)
65
- if (addr == MSG_MOTOR_20 ) {
66
- int gas = (GET_BYTES_04 (to_push ) >> 12 ) & 0xFF ;
67
- if ((gas > 0 ) && (volkswagen_gas_prev == 0 )) {
68
- controls_allowed = 0 ;
69
- }
70
- volkswagen_gas_prev = gas ;
71
- }
72
-
73
- if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT ) && (bus == 0 ) && (addr == MSG_HCA_01 )) {
74
- relay_malfunction = true;
75
- }
54
+ int bus = GET_BUS (to_push );
55
+ int addr = GET_ADDR (to_push );
56
+
57
+ // Update driver input torque samples
58
+ // Signal: EPS_01.Driver_Strain (absolute torque)
59
+ // Signal: EPS_01.Driver_Strain_VZ (direction)
60
+ if ((bus == 0 ) && (addr == MSG_EPS_01 )) {
61
+ int torque_driver_new = GET_BYTE (to_push , 5 ) | ((GET_BYTE (to_push , 6 ) & 0x1F ) << 8 );
62
+ int sign = (GET_BYTE (to_push , 6 ) & 0x80 ) >> 7 ;
63
+ if (sign == 1 ) {
64
+ torque_driver_new *= -1 ;
65
+ }
66
+ update_sample (& volkswagen_torque_driver , torque_driver_new );
67
+ }
68
+
69
+ // Update ACC status from radar for controls-allowed state
70
+ // Signal: ACC_06.ACC_Status_ACC
71
+ if ((bus == 0 ) && (addr == MSG_ACC_06 )) {
72
+ int acc_status = (GET_BYTE (to_push , 7 ) & 0x70 ) >> 4 ;
73
+ controls_allowed = ((acc_status == 3 ) || (acc_status == 4 ) || (acc_status == 5 )) ? 1 : 0 ;
74
+ }
75
+
76
+ // Exit controls on rising edge of gas press
77
+ // Signal: Motor_20.MO_Fahrpedalrohwert_01
78
+ if ((bus == 0 ) && (addr == MSG_MOTOR_20 )) {
79
+ int gas = (GET_BYTES_04 (to_push ) >> 12 ) & 0xFF ;
80
+ if ((gas > 0 ) && (volkswagen_gas_prev == 0 )) {
81
+ controls_allowed = 0 ;
82
+ }
83
+ volkswagen_gas_prev = gas ;
84
+ }
85
+
86
+ // If there are HCA messages on bus 0 not sent by OP, there's a relay problem
87
+ if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT ) && (bus == 0 ) && (addr == MSG_HCA_01 )) {
88
+ relay_malfunction = true;
89
+ }
76
90
}
77
91
return valid ;
78
92
}
79
93
80
- static int volkswagen_tx_hook (CAN_FIFOMailBox_TypeDef * to_send ) {
94
+ static bool volkswagen_steering_check (int desired_torque ) {
95
+ bool violation = false;
96
+ uint32_t ts = TIM2 -> CNT ;
97
+
98
+ if (controls_allowed ) {
99
+ // *** global torque limit check ***
100
+ violation |= max_limit_check (desired_torque , VOLKSWAGEN_MAX_STEER , - VOLKSWAGEN_MAX_STEER );
101
+
102
+ // *** torque rate limit check ***
103
+ violation |= driver_limit_check (desired_torque , volkswagen_desired_torque_last , & volkswagen_torque_driver ,
104
+ VOLKSWAGEN_MAX_STEER , VOLKSWAGEN_MAX_RATE_UP , VOLKSWAGEN_MAX_RATE_DOWN ,
105
+ VOLKSWAGEN_DRIVER_TORQUE_ALLOWANCE , VOLKSWAGEN_DRIVER_TORQUE_FACTOR );
106
+ volkswagen_desired_torque_last = desired_torque ;
107
+
108
+ // *** torque real time rate limit check ***
109
+ violation |= rt_rate_limit_check (desired_torque , volkswagen_rt_torque_last , VOLKSWAGEN_MAX_RT_DELTA );
110
+
111
+ // every RT_INTERVAL set the new limits
112
+ uint32_t ts_elapsed = get_ts_elapsed (ts , volkswagen_ts_last );
113
+ if (ts_elapsed > VOLKSWAGEN_RT_INTERVAL ) {
114
+ volkswagen_rt_torque_last = desired_torque ;
115
+ volkswagen_ts_last = ts ;
116
+ }
117
+ }
118
+
119
+ // no torque if controls is not allowed
120
+ if (!controls_allowed && (desired_torque != 0 )) {
121
+ violation = true;
122
+ }
123
+
124
+ // reset to 0 if either controls is not allowed or there's a violation
125
+ if (violation || !controls_allowed ) {
126
+ volkswagen_desired_torque_last = 0 ;
127
+ volkswagen_rt_torque_last = 0 ;
128
+ volkswagen_ts_last = ts ;
129
+ }
130
+
131
+ return violation ;
132
+ }
133
+
134
+ static int volkswagen_mqb_tx_hook (CAN_FIFOMailBox_TypeDef * to_send ) {
81
135
int addr = GET_ADDR (to_send );
82
136
int bus = GET_BUS (to_send );
83
137
int tx = 1 ;
84
138
85
- if (!msg_allowed (addr , bus , VOLKSWAGEN_TX_MSGS , sizeof (VOLKSWAGEN_TX_MSGS )/sizeof (VOLKSWAGEN_TX_MSGS [0 ]))) {
86
- tx = 0 ;
87
- }
88
-
89
- if (relay_malfunction ) {
139
+ if (!msg_allowed (addr , bus , VOLKSWAGEN_MQB_TX_MSGS , VOLKSWAGEN_MQB_TX_MSGS_LEN ) || relay_malfunction ) {
90
140
tx = 0 ;
91
141
}
92
142
93
- // Safety check for HCA_01 Heading Control Assist torque.
143
+ // Safety check for HCA_01 Heading Control Assist torque
144
+ // Signal: HCA_01.Assist_Torque (absolute torque)
145
+ // Signal: HCA_01.Assist_VZ (direction)
94
146
if (addr == MSG_HCA_01 ) {
95
- bool violation = false;
96
-
97
147
int desired_torque = GET_BYTE (to_send , 2 ) | ((GET_BYTE (to_send , 3 ) & 0x3F ) << 8 );
98
148
int sign = (GET_BYTE (to_send , 3 ) & 0x80 ) >> 7 ;
99
149
if (sign == 1 ) {
100
150
desired_torque *= -1 ;
101
151
}
102
152
103
- uint32_t ts = TIM2 -> CNT ;
104
-
105
- if (controls_allowed ) {
106
-
107
- // *** global torque limit check ***
108
- violation |= max_limit_check (desired_torque , VOLKSWAGEN_MAX_STEER , - VOLKSWAGEN_MAX_STEER );
109
-
110
- // *** torque rate limit check ***
111
- violation |= driver_limit_check (desired_torque , volkswagen_desired_torque_last , & volkswagen_torque_driver ,
112
- VOLKSWAGEN_MAX_STEER , VOLKSWAGEN_MAX_RATE_UP , VOLKSWAGEN_MAX_RATE_DOWN ,
113
- VOLKSWAGEN_DRIVER_TORQUE_ALLOWANCE , VOLKSWAGEN_DRIVER_TORQUE_FACTOR );
114
- volkswagen_desired_torque_last = desired_torque ;
115
-
116
- // *** torque real time rate limit check ***
117
- violation |= rt_rate_limit_check (desired_torque , volkswagen_rt_torque_last , VOLKSWAGEN_MAX_RT_DELTA );
118
-
119
- // every RT_INTERVAL set the new limits
120
- uint32_t ts_elapsed = get_ts_elapsed (ts , volkswagen_ts_last );
121
- if (ts_elapsed > VOLKSWAGEN_RT_INTERVAL ) {
122
- volkswagen_rt_torque_last = desired_torque ;
123
- volkswagen_ts_last = ts ;
124
- }
125
- }
126
-
127
- // no torque if controls is not allowed
128
- if (!controls_allowed && (desired_torque != 0 )) {
129
- violation = true;
130
- }
131
-
132
- // reset to 0 if either controls is not allowed or there's a violation
133
- if (violation || !controls_allowed ) {
134
- volkswagen_desired_torque_last = 0 ;
135
- volkswagen_rt_torque_last = 0 ;
136
- volkswagen_ts_last = ts ;
137
- }
138
-
139
- if (violation ) {
153
+ if (volkswagen_steering_check (desired_torque )) {
140
154
tx = 0 ;
141
155
}
142
156
}
@@ -158,38 +172,37 @@ static int volkswagen_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
158
172
int addr = GET_ADDR (to_fwd );
159
173
int bus_fwd = -1 ;
160
174
161
- // NOTE: Will need refactoring for other bus layouts, such as no-forwarding at camera or J533 running-gear CAN
162
-
163
175
if (!relay_malfunction ) {
164
176
switch (bus_num ) {
165
177
case 0 :
166
- // Forward all traffic from J533 gateway to Extended CAN devices.
178
+ // Forward all traffic from the Extended CAN onward
167
179
bus_fwd = 2 ;
168
180
break ;
169
181
case 2 :
170
- if ((addr == MSG_HCA_01 ) || (addr == MSG_LDW_02 )) {
171
- // OP takes control of the Heading Control Assist and Lane Departure Warning messages from the camera.
182
+ if ((addr == volkswagen_torque_msg ) || (addr == volkswagen_lane_msg )) {
183
+ // OP takes control of the Heading Control Assist and Lane Departure Warning messages from the camera
172
184
bus_fwd = -1 ;
173
185
} else {
174
- // Forward all remaining traffic from Extended CAN devices to J533 gateway.
186
+ // Forward all remaining traffic from Extended CAN devices to J533 gateway
175
187
bus_fwd = 0 ;
176
188
}
177
189
break ;
178
190
default :
179
- // No other buses should be in use; fallback to do-not-forward.
191
+ // No other buses should be in use; fallback to do-not-forward
180
192
bus_fwd = -1 ;
181
193
break ;
182
194
}
183
195
}
184
196
return bus_fwd ;
185
197
}
186
198
187
- const safety_hooks volkswagen_hooks = {
188
- .init = nooutput_init ,
189
- .rx = volkswagen_rx_hook ,
190
- .tx = volkswagen_tx_hook ,
199
+ // Volkswagen MQB platform
200
+ const safety_hooks volkswagen_mqb_hooks = {
201
+ .init = volkswagen_mqb_init ,
202
+ .rx = volkswagen_mqb_rx_hook ,
203
+ .tx = volkswagen_mqb_tx_hook ,
191
204
.tx_lin = nooutput_tx_lin_hook ,
192
205
.fwd = volkswagen_fwd_hook ,
193
- .addr_check = volkswagen_rx_checks ,
194
- .addr_check_len = sizeof (volkswagen_rx_checks ) / sizeof (volkswagen_rx_checks [0 ]),
206
+ .addr_check = volkswagen_mqb_rx_checks ,
207
+ .addr_check_len = sizeof (volkswagen_mqb_rx_checks ) / sizeof (volkswagen_mqb_rx_checks [0 ]),
195
208
};
0 commit comments