Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions board/drivers/can.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ void can_rx(uint8_t can_number) {
}
}

#ifndef CUSTOM_CAN_INTERRUPTS

void CAN1_TX_IRQHandler() { process_can(0); }
void CAN1_RX0_IRQHandler() { can_rx(0); }
void CAN1_SCE_IRQHandler() { can_sce(CAN1); }
Expand All @@ -386,6 +388,8 @@ void CAN3_RX0_IRQHandler() { can_rx(2); }
void CAN3_SCE_IRQHandler() { can_sce(CAN3); }
#endif

#endif

void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
if (safety_tx_hook(to_push)) {
if (bus_number < BUS_MAX) {
Expand Down
2 changes: 1 addition & 1 deletion board/drivers/drivers.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ uint32_t adc_get(int channel);
// ********************* DAC *********************

void dac_init();
uint32_t dac_set(int channel, uint32_t value);
void dac_set(int channel, uint32_t value);


// ********************* TIMER *********************
Expand Down
31 changes: 26 additions & 5 deletions board/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,15 @@ void clock_init() {
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE;
#else
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLSRC_HSE;
#ifdef PEDAL
// comma pedal has a 16mhz crystal
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE;
#else
// NEO board has a 8mhz crystal
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLSRC_HSE;
#endif
#endif

// start PLL
Expand Down Expand Up @@ -132,8 +139,13 @@ void set_can_enable(CAN_TypeDef *CAN, int enabled) {
// CAN1_EN
set_gpio_output(GPIOC, 1, !enabled);
#else
// CAN1_EN
set_gpio_output(GPIOB, 3, enabled);
#ifdef PEDAL
// CAN1_EN (not flipped)
set_gpio_output(GPIOB, 3, !enabled);
#else
// CAN1_EN
set_gpio_output(GPIOB, 3, enabled);
#endif
#endif
} else if (CAN == CAN2) {
#ifdef PANDA
Expand Down Expand Up @@ -285,6 +297,14 @@ void gpio_init() {
set_gpio_mode(GPIOC, 2, MODE_ANALOG);
set_gpio_mode(GPIOC, 3, MODE_ANALOG);

#ifdef PEDAL
// comma pedal has inputs on C0 and C1
set_gpio_mode(GPIOC, 0, MODE_ANALOG);
set_gpio_mode(GPIOC, 1, MODE_ANALOG);
// DAC outputs on A4 and A5
// apparently they don't need GPIO setup
#endif

// C8: FAN aka TIM3_CH4
set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3);

Expand Down Expand Up @@ -443,9 +463,10 @@ void early() {


if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
#ifdef PANDA
set_esp_mode(ESP_DISABLED);
#endif
set_led(LED_GREEN, 1);

jump_to_bootloader();
}

Expand Down
1 change: 1 addition & 0 deletions board/pedal/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
obj/*
32 changes: 32 additions & 0 deletions board/pedal/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# :set noet
PROJ_NAME = comma

CFLAGS = -O2 -Wall -std=gnu11
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3
CFLAGS += -msoft-float -DSTM32F2 -DSTM32F205xx
CFLAGS += -I ../inc -I ../ -nostdlib
CFLAGS += -T../stm32_flash.ld

CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy
OBJDUMP = arm-none-eabi-objdump

all: obj/$(PROJ_NAME).bin
#$(OBJDUMP) -d obj/$(PROJ_NAME).elf
dfu-util -d 0483:df11 -a 0 -s 0x08000000:leave -D $<

obj/main.o: main.c ../*.h
mkdir -p obj
$(CC) $(CFLAGS) -o $@ -c $<

obj/startup_stm32f205xx.o: ../startup_stm32f205xx.s
mkdir -p obj
$(CC) $(CFLAGS) -o $@ -c $<

obj/$(PROJ_NAME).bin: obj/startup_stm32f205xx.o obj/main.o
$(CC) $(CFLAGS) -o obj/$(PROJ_NAME).elf $^
$(OBJCOPY) -v -O binary obj/$(PROJ_NAME).elf $@

clean:
rm -f obj/*

6 changes: 6 additions & 0 deletions board/pedal/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This is the firmware for the comma pedal. It borrows a lot from panda.

The comma pedal is a gas pedal interceptor for Honda/Acura. It allows you to "virtually" press the pedal.

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

252 changes: 252 additions & 0 deletions board/pedal/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
//#define DEBUG
//#define CAN_LOOPBACK_MODE
//#define USE_INTERNAL_OSC

#define PEDAL

#include "../config.h"

#include "drivers/drivers.h"
#include "drivers/llgpio.h"
#include "gpio.h"

#define CUSTOM_CAN_INTERRUPTS

#include "libc.h"
#include "safety.h"
#include "drivers/adc.h"
#include "drivers/uart.h"
#include "drivers/dac.h"
#include "drivers/can.h"
#include "drivers/timer.h"

#define CAN CAN1

//#define PEDAL_USB

#ifdef PEDAL_USB
#include "drivers/usb.h"
#endif

#define ENTER_BOOTLOADER_MAGIC 0xdeadbeef
uint32_t enter_bootloader_mode;

void __initialize_hardware_early() {
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
enter_bootloader_mode = 0;
void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *)0x1fff0004));
bootloader();

// LOOP
while(1);
}
}

// ********************* serial debugging *********************

void debug_ring_callback(uart_ring *ring) {
char rcv;
while (getc(ring, &rcv)) {
putc(ring, rcv);
}
}

#ifdef PEDAL_USB

int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired) { return 0; }
void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) {}
void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) {}
void usb_cb_enumeration_complete() {}

int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
int resp_len = 0;
uart_ring *ur = NULL;
switch (setup->b.bRequest) {
// **** 0xe0: uart read
case 0xe0:
ur = get_ring_by_number(setup->b.wValue.w);
if (!ur) break;
if (ur == &esp_ring) uart_dma_drain();
// read
while ((resp_len < min(setup->b.wLength.w, MAX_RESP_LEN)) &&
getc(ur, (char*)&resp[resp_len])) {
++resp_len;
}
break;
}
return resp_len;
}

#endif

// ***************************** honda can checksum *****************************

int can_cksum(uint8_t *dat, int len, int addr, int idx) {
int i;
int s = 0;
for (i = 0; i < len; i++) {
s += (dat[i] >> 4);
s += dat[i] & 0xF;
}
s += (addr>>0)&0xF;
s += (addr>>4)&0xF;
s += (addr>>8)&0xF;
s += idx;
s = 8-s;
return s&0xF;
}

// ***************************** can port *****************************

// addresses to be used on CAN
#define CAN_GAS_INPUT 0x200
#define CAN_GAS_OUTPUT 0x201

void CAN1_TX_IRQHandler() {
// clear interrupt
CAN->TSR |= CAN_TSR_RQCP0;
}

uint16_t gas_set = 0;
uint32_t timeout = 0;
uint32_t current_index = 0;

void CAN1_RX0_IRQHandler() {
while (CAN->RF0R & CAN_RF0R_FMP0) {
#ifdef DEBUG
puts("CAN RX\n");
#endif
uint32_t address = CAN->sFIFOMailBox[0].RIR>>21;
if (address == CAN_GAS_INPUT) {
uint8_t *dat = (uint8_t *)&CAN->sFIFOMailBox[0].RDLR;
uint16_t value = (dat[0] << 8) | dat[1];
uint8_t index = (dat[2] >> 4) & 3;
if (can_cksum(dat, 2, CAN_GAS_INPUT, index) == (dat[2] & 0xF)) {
if (((current_index+1)&3) == index) {
// TODO: set and start timeout
#ifdef DEBUG
puts("setting gas ");
puth(value);
puts("\n");
#endif
gas_set = value;
timeout = 0;
}
// TODO: better lockout? prevents same spam
current_index = index;
}
}
// next
CAN->RF0R |= CAN_RF0R_RFOM0;
}
}

void CAN1_SCE_IRQHandler() {
can_sce(CAN);
}

int pdl0 = 0, pdl1 = 0;
int pkt_idx = 0;

int led_value = 0;

void TIM3_IRQHandler() {
#ifdef DEBUG
puth(TIM3->CNT);
puts(" ");
puth(pdl0);
puts(" ");
puth(pdl1);
puts("\n");
#endif

// check timer for sending the user pedal and clearing the CAN
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
uint8_t *dat = (uint8_t *)&CAN->sTxMailBox[0].TDLR;
CAN->sTxMailBox[0].TDLR = (((pdl0>>8)&0xFF)<<0) |
(((pdl0>>0)&0xFF)<<8) |
(((pdl1>>8)&0xFF)<<16) |
(((pdl1>>0)&0xFF)<<24);
CAN->sTxMailBox[0].TDHR = can_cksum(dat, 4, CAN_GAS_OUTPUT, pkt_idx) | (pkt_idx << 4);
CAN->sTxMailBox[0].TDTR = 5; // len of packet is 4
CAN->sTxMailBox[0].TIR = (CAN_GAS_OUTPUT << 21) | 1;
++pkt_idx;
pkt_idx &= 3;
} else {
// old can packet hasn't sent!
// TODO: do something?
#ifdef DEBUG
puts("CAN MISS\n");
#endif
}


// blink the LED
set_led(LED_GREEN, led_value);
led_value = !led_value;

TIM3->SR = 0;

// up timeout for gas set
timeout++;
}

// ***************************** main code *****************************

void pedal() {
// read/write
pdl0 = adc_get(ADCCHAN_ACCEL0);
pdl1 = adc_get(ADCCHAN_ACCEL1);

// write the pedal to the DAC
if (timeout < 10) {
dac_set(0, max(gas_set, pdl0));
dac_set(1, max(gas_set*2, pdl1));
} else {
dac_set(0, pdl0);
dac_set(1, pdl1);
}
}

int main() {
__disable_irq();

// init devices
clock_init();
periph_init();
gpio_init();

#ifdef PEDAL_USB
// enable USB
usb_init();
#endif

// pedal stuff
dac_init();
adc_init();

// init can
can_silent = ALL_CAN_LIVE;
can_init_all();

// 48mhz / 65536 ~= 732
timer_init(TIM3, 15);

// needed?
NVIC_EnableIRQ(CAN1_TX_IRQn);
NVIC_EnableIRQ(CAN1_RX0_IRQn);
NVIC_EnableIRQ(CAN1_SCE_IRQn);

NVIC_EnableIRQ(TIM3_IRQn);

puts("**** INTERRUPTS ON ****\n");
__enable_irq();

// main pedal loop
while (1) {
pedal();
}

return 0;
}

2 changes: 1 addition & 1 deletion tests/can_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def can_printer():
if sec_since_boot() - lp > 0.1:
dd = chr(27) + "[2J"
dd += "%5.2f\n" % (sec_since_boot() - start)
for k,v in sorted(zip(msgs.keys(), map(lambda x: x[-1].encode("hex"), msgs.values()))):
for k,v in sorted(zip(msgs.keys(), map(lambda x: str(x[-1]).encode("hex"), msgs.values()))):
dd += "%s(%6d) %s\n" % ("%04X(%4d)" % (k,k),len(msgs[k]), v)
print(dd)
lp = sec_since_boot()
Expand Down