Skip to content

Commit 23de8d4

Browse files
authored
Merge pull request #97 from commaai/pedal_improvements
Pedal improvements
2 parents 1b77026 + e2f73d2 commit 23de8d4

File tree

2 files changed

+83
-20
lines changed

2 files changed

+83
-20
lines changed

board/pedal/README

+22
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,25 @@ The comma pedal is a gas pedal interceptor for Honda/Acura. It allows you to "vi
44

55
This is the open source software. Open source hardware coming soon.
66

7+
== Test Plan ==
8+
9+
* Startup
10+
** Confirm STATE_FAULT_STARTUP
11+
* Timeout
12+
** Send value
13+
** Confirm value is output
14+
** Stop sending messages
15+
** Confirm value is passthru after 100ms
16+
** Confirm STATE_FAULT_TIMEOUT
17+
* Random values
18+
** Send random 6 byte messages
19+
** Confirm random values cause passthru
20+
** Confirm STATE_FAULT_BAD_CHECKSUM
21+
* Same message lockout
22+
** Send same message repeated
23+
** Confirm timeout behavior
24+
* Don't set enable
25+
** Confirm no output
26+
* Set enable and values
27+
** Confirm output
28+

board/pedal/main.c

+61-20
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,22 @@ void CAN1_TX_IRQHandler() {
107107
CAN->TSR |= CAN_TSR_RQCP0;
108108
}
109109

110-
uint16_t gas_set = 0;
110+
// two independent values
111+
uint16_t gas_set_0 = 0;
112+
uint16_t gas_set_1 = 0;
113+
114+
#define MAX_TIMEOUT 10
111115
uint32_t timeout = 0;
112116
uint32_t current_index = 0;
113117

118+
#define NO_FAULT 0
119+
#define FAULT_BAD_CHECKSUM 1
120+
#define FAULT_SEND 2
121+
#define FAULT_SCE 3
122+
#define FAULT_STARTUP 4
123+
#define FAULT_TIMEOUT 5
124+
uint8_t state = FAULT_STARTUP;
125+
114126
void CAN1_RX0_IRQHandler() {
115127
while (CAN->RF0R & CAN_RF0R_FMP0) {
116128
#ifdef DEBUG
@@ -119,21 +131,33 @@ void CAN1_RX0_IRQHandler() {
119131
uint32_t address = CAN->sFIFOMailBox[0].RIR>>21;
120132
if (address == CAN_GAS_INPUT) {
121133
uint8_t *dat = (uint8_t *)&CAN->sFIFOMailBox[0].RDLR;
122-
uint16_t value = (dat[0] << 8) | dat[1];
123-
uint8_t index = (dat[2] >> 4) & 3;
124-
if (can_cksum(dat, 2, CAN_GAS_INPUT, index) == (dat[2] & 0xF)) {
134+
uint8_t *dat2 = (uint8_t *)&CAN->sFIFOMailBox[0].RDHR;
135+
uint16_t value_0 = (dat[0] << 8) | dat[1];
136+
uint16_t value_1 = (dat[2] << 8) | dat[3];
137+
uint8_t enable = (dat2[0] >> 7) & 1;
138+
uint8_t index = (dat2[1] >> 4) & 3;
139+
if (can_cksum(dat, 5, CAN_GAS_INPUT, index) == (dat2[1] & 0xF)) {
125140
if (((current_index+1)&3) == index) {
126-
// TODO: set and start timeout
127141
#ifdef DEBUG
128142
puts("setting gas ");
129143
puth(value);
130144
puts("\n");
131145
#endif
132-
gas_set = value;
146+
if (enable) {
147+
gas_set_0 = value_0;
148+
gas_set_1 = value_1;
149+
} else {
150+
// clear the fault state if values are 0
151+
if (value_0 == 0 && value_1 == 0) state = NO_FAULT;
152+
gas_set_0 = gas_set_1 = 0;
153+
}
154+
// clear the timeout
133155
timeout = 0;
134156
}
135-
// TODO: better lockout? prevents same spam
136157
current_index = index;
158+
} else {
159+
// wrong checksum = fault
160+
state = FAULT_BAD_CHECKSUM;
137161
}
138162
}
139163
// next
@@ -142,6 +166,7 @@ void CAN1_RX0_IRQHandler() {
142166
}
143167

144168
void CAN1_SCE_IRQHandler() {
169+
state = FAULT_SCE;
145170
can_sce(CAN);
146171
}
147172

@@ -162,33 +187,39 @@ void TIM3_IRQHandler() {
162187

163188
// check timer for sending the user pedal and clearing the CAN
164189
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
165-
uint8_t *dat = (uint8_t *)&CAN->sTxMailBox[0].TDLR;
166-
CAN->sTxMailBox[0].TDLR = (((pdl0>>8)&0xFF)<<0) |
167-
(((pdl0>>0)&0xFF)<<8) |
168-
(((pdl1>>8)&0xFF)<<16) |
169-
(((pdl1>>0)&0xFF)<<24);
170-
CAN->sTxMailBox[0].TDHR = can_cksum(dat, 4, CAN_GAS_OUTPUT, pkt_idx) | (pkt_idx << 4);
171-
CAN->sTxMailBox[0].TDTR = 5; // len of packet is 4
190+
uint8_t dat[8];
191+
dat[0] = (pdl0>>8)&0xFF;
192+
dat[1] = (pdl0>>0)&0xFF;
193+
dat[2] = (pdl1>>8)&0xFF;
194+
dat[3] = (pdl1>>0)&0xFF;
195+
dat[4] = state;
196+
dat[5] = can_cksum(dat, 5, CAN_GAS_OUTPUT, pkt_idx);
197+
CAN->sTxMailBox[0].TDLR = dat[0] | (dat[1]<<8) | (dat[2]<<16) | (dat[3]<<24);
198+
CAN->sTxMailBox[0].TDHR = dat[4] | (dat[5]<<8);
199+
CAN->sTxMailBox[0].TDTR = 6; // len of packet is 5
172200
CAN->sTxMailBox[0].TIR = (CAN_GAS_OUTPUT << 21) | 1;
173201
++pkt_idx;
174202
pkt_idx &= 3;
175203
} else {
176204
// old can packet hasn't sent!
177-
// TODO: do something?
205+
state = FAULT_SEND;
178206
#ifdef DEBUG
179207
puts("CAN MISS\n");
180208
#endif
181209
}
182210

183-
184211
// blink the LED
185212
set_led(LED_GREEN, led_value);
186213
led_value = !led_value;
187214

188215
TIM3->SR = 0;
189216

190217
// up timeout for gas set
191-
timeout++;
218+
if (timeout == MAX_TIMEOUT) {
219+
state = FAULT_TIMEOUT;
220+
} else {
221+
timeout += 1;
222+
}
192223
}
193224

194225
// ***************************** main code *****************************
@@ -199,13 +230,16 @@ void pedal() {
199230
pdl1 = adc_get(ADCCHAN_ACCEL1);
200231

201232
// write the pedal to the DAC
202-
if (timeout < 10) {
203-
dac_set(0, max(gas_set, pdl0));
204-
dac_set(1, max(gas_set*2, pdl1));
233+
if (timeout < MAX_TIMEOUT && state == NO_FAULT) {
234+
dac_set(0, max(gas_set_0, pdl0));
235+
dac_set(1, max(gas_set_1, pdl1));
205236
} else {
206237
dac_set(0, pdl0);
207238
dac_set(1, pdl1);
208239
}
240+
241+
// feed the watchdog
242+
IWDG->KR = 0xAAAA;
209243
}
210244

211245
int main() {
@@ -239,6 +273,13 @@ int main() {
239273

240274
NVIC_EnableIRQ(TIM3_IRQn);
241275

276+
// setup watchdog
277+
IWDG->KR = 0x5555;
278+
IWDG->PR = 0; // divider /4
279+
// 0 = 0.125 ms, let's have a 50ms watchdog
280+
IWDG->RLR = 400 - 1;
281+
IWDG->KR = 0xCCCC;
282+
242283
puts("**** INTERRUPTS ON ****\n");
243284
__enable_irq();
244285

0 commit comments

Comments
 (0)