openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

308 lines
9.5 KiB

// ///////////////////////// //
// Jungle board v2 (STM32H7) //
// ///////////////////////// //
gpio_t power_pins[] = {
{.bank = GPIOA, .pin = 0},
{.bank = GPIOA, .pin = 1},
{.bank = GPIOF, .pin = 12},
{.bank = GPIOA, .pin = 5},
{.bank = GPIOC, .pin = 5},
{.bank = GPIOB, .pin = 2},
};
gpio_t sbu1_ignition_pins[] = {
{.bank = GPIOD, .pin = 0},
{.bank = GPIOD, .pin = 5},
{.bank = GPIOD, .pin = 12},
{.bank = GPIOD, .pin = 14},
{.bank = GPIOE, .pin = 5},
{.bank = GPIOE, .pin = 9},
};
gpio_t sbu1_relay_pins[] = {
{.bank = GPIOD, .pin = 1},
{.bank = GPIOD, .pin = 6},
{.bank = GPIOD, .pin = 11},
{.bank = GPIOD, .pin = 15},
{.bank = GPIOE, .pin = 6},
{.bank = GPIOE, .pin = 10},
};
gpio_t sbu2_ignition_pins[] = {
{.bank = GPIOD, .pin = 3},
{.bank = GPIOD, .pin = 8},
{.bank = GPIOD, .pin = 9},
{.bank = GPIOE, .pin = 0},
{.bank = GPIOE, .pin = 7},
{.bank = GPIOE, .pin = 11},
};
gpio_t sbu2_relay_pins[] = {
{.bank = GPIOD, .pin = 4},
{.bank = GPIOD, .pin = 10},
{.bank = GPIOD, .pin = 13},
{.bank = GPIOE, .pin = 1},
{.bank = GPIOE, .pin = 8},
{.bank = GPIOE, .pin = 12},
};
adc_channel_t sbu1_channels[] = {
{.adc = ADC3, .channel = 12},
{.adc = ADC3, .channel = 2},
{.adc = ADC3, .channel = 4},
{.adc = ADC3, .channel = 6},
{.adc = ADC3, .channel = 8},
{.adc = ADC3, .channel = 10},
};
adc_channel_t sbu2_channels[] = {
{.adc = ADC1, .channel = 13},
{.adc = ADC3, .channel = 3},
{.adc = ADC3, .channel = 5},
{.adc = ADC3, .channel = 7},
{.adc = ADC3, .channel = 9},
{.adc = ADC3, .channel = 11},
};
void board_v2_set_harness_orientation(uint8_t orientation) {
switch (orientation) {
case HARNESS_ORIENTATION_NONE:
gpio_set_all_output(sbu1_ignition_pins, sizeof(sbu1_ignition_pins) / sizeof(gpio_t), false);
gpio_set_all_output(sbu1_relay_pins, sizeof(sbu1_relay_pins) / sizeof(gpio_t), false);
gpio_set_all_output(sbu2_ignition_pins, sizeof(sbu2_ignition_pins) / sizeof(gpio_t), false);
gpio_set_all_output(sbu2_relay_pins, sizeof(sbu2_relay_pins) / sizeof(gpio_t), false);
harness_orientation = orientation;
break;
case HARNESS_ORIENTATION_1:
gpio_set_all_output(sbu1_ignition_pins, sizeof(sbu1_ignition_pins) / sizeof(gpio_t), false);
gpio_set_all_output(sbu1_relay_pins, sizeof(sbu1_relay_pins) / sizeof(gpio_t), true);
gpio_set_bitmask(sbu2_ignition_pins, sizeof(sbu2_ignition_pins) / sizeof(gpio_t), ignition);
gpio_set_all_output(sbu2_relay_pins, sizeof(sbu2_relay_pins) / sizeof(gpio_t), false);
harness_orientation = orientation;
break;
case HARNESS_ORIENTATION_2:
gpio_set_bitmask(sbu1_ignition_pins, sizeof(sbu1_ignition_pins) / sizeof(gpio_t), ignition);
gpio_set_all_output(sbu1_relay_pins, sizeof(sbu1_relay_pins) / sizeof(gpio_t), false);
gpio_set_all_output(sbu2_ignition_pins, sizeof(sbu2_ignition_pins) / sizeof(gpio_t), false);
gpio_set_all_output(sbu2_relay_pins, sizeof(sbu2_relay_pins) / sizeof(gpio_t), true);
harness_orientation = orientation;
break;
default:
print("Tried to set an unsupported harness orientation: "); puth(orientation); print("\n");
break;
}
}
void board_v2_enable_can_transceiver(uint8_t transceiver, bool enabled) {
switch (transceiver) {
case 1U:
set_gpio_output(GPIOG, 11, !enabled);
break;
case 2U:
set_gpio_output(GPIOB, 3, !enabled);
break;
case 3U:
set_gpio_output(GPIOD, 7, !enabled);
break;
case 4U:
set_gpio_output(GPIOB, 4, !enabled);
break;
default:
print("Invalid CAN transceiver ("); puth(transceiver); print("): enabling failed\n");
break;
}
}
void board_v2_enable_header_pin(uint8_t pin_num, bool enabled) {
if (pin_num < 8U) {
set_gpio_output(GPIOG, pin_num, enabled);
} else {
print("Invalid pin number ("); puth(pin_num); print("): enabling failed\n");
}
}
void board_v2_set_can_mode(uint8_t mode) {
board_v2_enable_can_transceiver(2U, false);
board_v2_enable_can_transceiver(4U, false);
switch (mode) {
case CAN_MODE_NORMAL:
// B12,B13: disable normal mode
set_gpio_pullup(GPIOB, 12, PULL_NONE);
set_gpio_mode(GPIOB, 12, MODE_ANALOG);
set_gpio_pullup(GPIOB, 13, PULL_NONE);
set_gpio_mode(GPIOB, 13, MODE_ANALOG);
// B5,B6: FDCAN2 mode
set_gpio_pullup(GPIOB, 5, PULL_NONE);
set_gpio_alternate(GPIOB, 5, GPIO_AF9_FDCAN2);
set_gpio_pullup(GPIOB, 6, PULL_NONE);
set_gpio_alternate(GPIOB, 6, GPIO_AF9_FDCAN2);
can_mode = CAN_MODE_NORMAL;
board_v2_enable_can_transceiver(2U, true);
break;
case CAN_MODE_OBD_CAN2:
// B5,B6: disable normal mode
set_gpio_pullup(GPIOB, 5, PULL_NONE);
set_gpio_mode(GPIOB, 5, MODE_ANALOG);
set_gpio_pullup(GPIOB, 6, PULL_NONE);
set_gpio_mode(GPIOB, 6, MODE_ANALOG);
// B12,B13: FDCAN2 mode
set_gpio_pullup(GPIOB, 12, PULL_NONE);
set_gpio_alternate(GPIOB, 12, GPIO_AF9_FDCAN2);
set_gpio_pullup(GPIOB, 13, PULL_NONE);
set_gpio_alternate(GPIOB, 13, GPIO_AF9_FDCAN2);
can_mode = CAN_MODE_OBD_CAN2;
board_v2_enable_can_transceiver(4U, true);
break;
default:
break;
}
}
bool panda_power = false;
uint8_t panda_power_bitmask = 0U;
void board_v2_set_panda_power(bool enable) {
panda_power = enable;
gpio_set_all_output(power_pins, sizeof(power_pins) / sizeof(gpio_t), enable);
if (enable) {
panda_power_bitmask = 0xFFU;
} else {
panda_power_bitmask = 0U;
}
}
void board_v2_set_panda_individual_power(uint8_t port_num, bool enable) {
port_num -= 1U;
if (port_num < 6U) {
panda_power_bitmask &= ~(1U << port_num);
panda_power_bitmask |= (enable ? 1U : 0U) << port_num;
} else {
print("Invalid port number ("); puth(port_num); print("): enabling failed\n");
}
gpio_set_bitmask(power_pins, sizeof(power_pins) / sizeof(gpio_t), (uint32_t)panda_power_bitmask);
}
bool board_v2_get_button(void) {
return get_gpio_input(GPIOG, 15);
}
void board_v2_set_ignition(bool enabled) {
ignition = enabled ? 0xFFU : 0U;
board_v2_set_harness_orientation(harness_orientation);
}
void board_v2_set_individual_ignition(uint8_t bitmask) {
ignition = bitmask;
board_v2_set_harness_orientation(harness_orientation);
}
float board_v2_get_channel_power(uint8_t channel) {
float ret = 0.0f;
if ((channel >= 1U) && (channel <= 6U)) {
uint16_t readout = adc_get_mV(ADC1, channel - 1U); // these are mapped nicely in hardware
ret = (((float) readout / 33e6) - 0.8e-6) / 52e-6 * 12.0f;
} else {
print("Invalid channel ("); puth(channel); print(")\n");
}
return ret;
}
uint16_t board_v2_get_sbu_mV(uint8_t channel, uint8_t sbu) {
uint16_t ret = 0U;
if ((channel >= 1U) && (channel <= 6U)) {
switch(sbu){
case SBU1:
ret = adc_get_mV(sbu1_channels[channel - 1U].adc, sbu1_channels[channel - 1U].channel);
break;
case SBU2:
ret = adc_get_mV(sbu2_channels[channel - 1U].adc, sbu2_channels[channel - 1U].channel);
break;
default:
print("Invalid SBU ("); puth(sbu); print(")\n");
break;
}
} else {
print("Invalid channel ("); puth(channel); print(")\n");
}
return ret;
}
void board_v2_init(void) {
common_init_gpio();
// Normal CAN mode
board_v2_set_can_mode(CAN_MODE_NORMAL);
// Enable CAN transceivers
for(uint8_t i = 1; i <= 4; i++) {
board_v2_enable_can_transceiver(i, true);
}
// Set to no harness orientation
board_v2_set_harness_orientation(HARNESS_ORIENTATION_NONE);
// Enable panda power by default
board_v2_set_panda_power(true);
// Current monitor channels
adc_init(ADC1);
register_set_bits(&SYSCFG->PMCR, SYSCFG_PMCR_PA0SO | SYSCFG_PMCR_PA1SO); // open up analog switches for PA0_C and PA1_C
set_gpio_mode(GPIOF, 11, MODE_ANALOG);
set_gpio_mode(GPIOA, 6, MODE_ANALOG);
set_gpio_mode(GPIOC, 4, MODE_ANALOG);
set_gpio_mode(GPIOB, 1, MODE_ANALOG);
// SBU channels
adc_init(ADC3);
set_gpio_mode(GPIOC, 2, MODE_ANALOG);
set_gpio_mode(GPIOC, 3, MODE_ANALOG);
set_gpio_mode(GPIOF, 9, MODE_ANALOG);
set_gpio_mode(GPIOF, 7, MODE_ANALOG);
set_gpio_mode(GPIOF, 5, MODE_ANALOG);
set_gpio_mode(GPIOF, 3, MODE_ANALOG);
set_gpio_mode(GPIOF, 10, MODE_ANALOG);
set_gpio_mode(GPIOF, 8, MODE_ANALOG);
set_gpio_mode(GPIOF, 6, MODE_ANALOG);
set_gpio_mode(GPIOF, 4, MODE_ANALOG);
set_gpio_mode(GPIOC, 0, MODE_ANALOG);
set_gpio_mode(GPIOC, 1, MODE_ANALOG);
// Header pins
set_gpio_mode(GPIOG, 0, MODE_OUTPUT);
set_gpio_mode(GPIOG, 1, MODE_OUTPUT);
set_gpio_mode(GPIOG, 2, MODE_OUTPUT);
set_gpio_mode(GPIOG, 3, MODE_OUTPUT);
set_gpio_mode(GPIOG, 4, MODE_OUTPUT);
set_gpio_mode(GPIOG, 5, MODE_OUTPUT);
set_gpio_mode(GPIOG, 6, MODE_OUTPUT);
set_gpio_mode(GPIOG, 7, MODE_OUTPUT);
}
void board_v2_tick(void) {}
board board_v2 = {
.has_canfd = true,
.has_sbu_sense = true,
.avdd_mV = 3300U,
.init = &board_v2_init,
.led_GPIO = {GPIOE, GPIOE, GPIOE},
.led_pin = {4, 3, 2},
.board_tick = &board_v2_tick,
.get_button = &board_v2_get_button,
.set_panda_power = &board_v2_set_panda_power,
.set_panda_individual_power = &board_v2_set_panda_individual_power,
.set_ignition = &board_v2_set_ignition,
.set_individual_ignition = &board_v2_set_individual_ignition,
.set_harness_orientation = &board_v2_set_harness_orientation,
.set_can_mode = &board_v2_set_can_mode,
.enable_can_transceiver = &board_v2_enable_can_transceiver,
.enable_header_pin = &board_v2_enable_header_pin,
.get_channel_power = &board_v2_get_channel_power,
.get_sbu_mV = &board_v2_get_sbu_mV,
};