mirror of
https://github.com/infiniteCable2/panda.git
synced 2026-02-18 09:13:52 +08:00
Continuous harness detection (#1402)
* read in mV and make threshold board-dependent * refactor and add SBU voltages to health * refactor relay driving * more refactoring and readout lock * avoid race condition * fix misra * continuous detection * 1Hz is fine * another race condition * use harness detection to trigger bootkick * update orientation detection test * more in-depth harness tests * fix ignition * fix * raise threshold
This commit is contained in:
@@ -25,7 +25,7 @@ void black_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
void black_enable_can_transceivers(bool enabled) {
|
||||
for(uint8_t i=1U; i<=4U; i++){
|
||||
// Leave main CAN always on for CAN-based ignition detection
|
||||
if((car_harness_status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){
|
||||
if((harness.status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){
|
||||
black_enable_can_transceiver(i, true);
|
||||
} else {
|
||||
black_enable_can_transceiver(i, enabled);
|
||||
@@ -83,7 +83,7 @@ void black_set_can_mode(uint8_t mode){
|
||||
switch (mode) {
|
||||
case CAN_MODE_NORMAL:
|
||||
case CAN_MODE_OBD_CAN2:
|
||||
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(car_harness_status == HARNESS_STATUS_FLIPPED)) {
|
||||
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(harness.status == HARNESS_STATUS_FLIPPED)) {
|
||||
// B12,B13: disable OBD mode
|
||||
set_gpio_mode(GPIOB, 12, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
@@ -160,7 +160,7 @@ void black_init(void) {
|
||||
black_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (car_harness_status == HARNESS_STATUS_FLIPPED) {
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ typedef void (*board_set_ir_power)(uint8_t percentage);
|
||||
typedef void (*board_set_fan_enabled)(bool enabled);
|
||||
typedef void (*board_set_phone_power)(bool enabled);
|
||||
typedef void (*board_set_siren)(bool enabled);
|
||||
typedef void (*board_board_tick)(bool ignition, bool usb_enum, bool heartbeat_seen);
|
||||
typedef void (*board_board_tick)(bool ignition, bool usb_enum, bool heartbeat_seen, bool harness_inserted);
|
||||
typedef bool (*board_read_som_gpio)(void);
|
||||
|
||||
struct board {
|
||||
|
||||
@@ -25,7 +25,7 @@ void dos_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
void dos_enable_can_transceivers(bool enabled) {
|
||||
for(uint8_t i=1U; i<=4U; i++){
|
||||
// Leave main CAN always on for CAN-based ignition detection
|
||||
if((car_harness_status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){
|
||||
if((harness.status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){
|
||||
dos_enable_can_transceiver(i, true);
|
||||
} else {
|
||||
dos_enable_can_transceiver(i, enabled);
|
||||
@@ -53,9 +53,9 @@ void dos_set_bootkick(bool enabled){
|
||||
set_gpio_output(GPIOC, 4, !enabled);
|
||||
}
|
||||
|
||||
void dos_board_tick(bool ignition, bool usb_enum, bool heartbeat_seen) {
|
||||
if (ignition && !usb_enum) {
|
||||
// enable bootkick if ignition seen
|
||||
void dos_board_tick(bool ignition, bool usb_enum, bool heartbeat_seen, bool harness_inserted) {
|
||||
if ((ignition && !usb_enum) || harness_inserted) {
|
||||
// enable bootkick if ignition seen or if plugged into a harness
|
||||
dos_set_bootkick(true);
|
||||
} else if (heartbeat_seen) {
|
||||
// disable once openpilot is up
|
||||
@@ -69,7 +69,7 @@ void dos_set_can_mode(uint8_t mode){
|
||||
switch (mode) {
|
||||
case CAN_MODE_NORMAL:
|
||||
case CAN_MODE_OBD_CAN2:
|
||||
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(car_harness_status == HARNESS_STATUS_FLIPPED)) {
|
||||
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(harness.status == HARNESS_STATUS_FLIPPED)) {
|
||||
// B12,B13: disable OBD mode
|
||||
set_gpio_mode(GPIOB, 12, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
@@ -177,7 +177,7 @@ void dos_init(void) {
|
||||
dos_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (car_harness_status == HARNESS_STATUS_FLIPPED) {
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ void red_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
}
|
||||
|
||||
void red_enable_can_transceivers(bool enabled) {
|
||||
uint8_t main_bus = (car_harness_status == HARNESS_STATUS_FLIPPED) ? 3U : 1U;
|
||||
uint8_t main_bus = (harness.status == HARNESS_STATUS_FLIPPED) ? 3U : 1U;
|
||||
for (uint8_t i=1U; i<=4U; i++) {
|
||||
// Leave main CAN always on for CAN-based ignition detection
|
||||
if (i == main_bus) {
|
||||
@@ -53,7 +53,7 @@ void red_set_can_mode(uint8_t mode) {
|
||||
switch (mode) {
|
||||
case CAN_MODE_NORMAL:
|
||||
case CAN_MODE_OBD_CAN2:
|
||||
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(car_harness_status == HARNESS_STATUS_FLIPPED)) {
|
||||
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(harness.status == HARNESS_STATUS_FLIPPED)) {
|
||||
// B12,B13: disable normal mode
|
||||
set_gpio_pullup(GPIOB, 12, PULL_NONE);
|
||||
set_gpio_mode(GPIOB, 12, MODE_ANALOG);
|
||||
@@ -147,7 +147,7 @@ void red_init(void) {
|
||||
red_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (car_harness_status == HARNESS_STATUS_FLIPPED) {
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ void red_chiplet_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
}
|
||||
|
||||
void red_chiplet_enable_can_transceivers(bool enabled) {
|
||||
uint8_t main_bus = (car_harness_status == HARNESS_STATUS_FLIPPED) ? 3U : 1U;
|
||||
uint8_t main_bus = (harness.status == HARNESS_STATUS_FLIPPED) ? 3U : 1U;
|
||||
for (uint8_t i=1U; i<=4U; i++) {
|
||||
// Leave main CAN always on for CAN-based ignition detection
|
||||
if (i == main_bus) {
|
||||
@@ -92,7 +92,7 @@ void red_chiplet_init(void) {
|
||||
red_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (car_harness_status == HARNESS_STATUS_FLIPPED) {
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ void tres_set_bootkick(bool enabled){
|
||||
}
|
||||
|
||||
bool tres_ignition_prev = false;
|
||||
void tres_board_tick(bool ignition, bool usb_enum, bool heartbeat_seen) {
|
||||
void tres_board_tick(bool ignition, bool usb_enum, bool heartbeat_seen, bool harness_inserted) {
|
||||
UNUSED(usb_enum);
|
||||
if (ignition && !tres_ignition_prev) {
|
||||
if ((ignition && !tres_ignition_prev) || harness_inserted) {
|
||||
// enable bootkick on rising edge of ignition
|
||||
tres_set_bootkick(true);
|
||||
} else if (heartbeat_seen) {
|
||||
|
||||
@@ -27,7 +27,7 @@ void uno_enable_can_transceiver(uint8_t transceiver, bool enabled) {
|
||||
void uno_enable_can_transceivers(bool enabled) {
|
||||
for(uint8_t i=1U; i<=4U; i++){
|
||||
// Leave main CAN always on for CAN-based ignition detection
|
||||
if((car_harness_status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){
|
||||
if((harness.status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){
|
||||
uno_enable_can_transceiver(i, true);
|
||||
} else {
|
||||
uno_enable_can_transceiver(i, enabled);
|
||||
@@ -102,7 +102,7 @@ void uno_set_can_mode(uint8_t mode){
|
||||
switch (mode) {
|
||||
case CAN_MODE_NORMAL:
|
||||
case CAN_MODE_OBD_CAN2:
|
||||
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(car_harness_status == HARNESS_STATUS_FLIPPED)) {
|
||||
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(harness.status == HARNESS_STATUS_FLIPPED)) {
|
||||
// B12,B13: disable OBD mode
|
||||
set_gpio_mode(GPIOB, 12, MODE_INPUT);
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
@@ -126,10 +126,11 @@ void uno_set_can_mode(uint8_t mode){
|
||||
}
|
||||
}
|
||||
|
||||
void uno_board_tick(bool ignition, bool usb_enum, bool heartbeat_seen) {
|
||||
void uno_board_tick(bool ignition, bool usb_enum, bool heartbeat_seen, bool harness_inserted) {
|
||||
UNUSED(ignition);
|
||||
UNUSED(usb_enum);
|
||||
UNUSED(heartbeat_seen);
|
||||
UNUSED(harness_inserted);
|
||||
if (bootkick_timer != 0U) {
|
||||
bootkick_timer--;
|
||||
} else {
|
||||
@@ -210,7 +211,7 @@ void uno_init(void) {
|
||||
uno_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// flip CAN0 and CAN2 if we are flipped
|
||||
if (car_harness_status == HARNESS_STATUS_FLIPPED) {
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
can_flip_buses(0, 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,11 @@ uint32_t unused_read_current(void) {
|
||||
return 0U;
|
||||
}
|
||||
|
||||
void unused_board_tick(bool ignition, bool usb_enum, bool heartbeat_seen) {
|
||||
void unused_board_tick(bool ignition, bool usb_enum, bool heartbeat_seen, bool harness_inserted) {
|
||||
UNUSED(ignition);
|
||||
UNUSED(usb_enum);
|
||||
UNUSED(heartbeat_seen);
|
||||
UNUSED(harness_inserted);
|
||||
}
|
||||
|
||||
bool unused_read_som_gpio(void) {
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
uint8_t car_harness_status = 0U;
|
||||
#define HARNESS_STATUS_NC 0U
|
||||
#define HARNESS_STATUS_NORMAL 1U
|
||||
#define HARNESS_STATUS_FLIPPED 2U
|
||||
|
||||
struct harness_t {
|
||||
uint8_t status;
|
||||
uint16_t sbu1_voltage_mV;
|
||||
uint16_t sbu2_voltage_mV;
|
||||
bool relay_driven;
|
||||
bool sbu_adc_lock;
|
||||
};
|
||||
struct harness_t harness;
|
||||
|
||||
struct harness_configuration {
|
||||
const bool has_harness;
|
||||
GPIO_TypeDef *GPIO_SBU1;
|
||||
@@ -17,26 +25,40 @@ struct harness_configuration {
|
||||
uint8_t adc_channel_SBU2;
|
||||
};
|
||||
|
||||
// this function will be the API for tici
|
||||
void set_intercept_relay(bool intercept) {
|
||||
if (car_harness_status != HARNESS_STATUS_NC) {
|
||||
if (intercept) {
|
||||
print("switching harness to intercept (relay on)\n");
|
||||
} else {
|
||||
print("switching harness to passthrough (relay off)\n");
|
||||
}
|
||||
bool drive_relay = intercept;
|
||||
if (harness.status == HARNESS_STATUS_NC) {
|
||||
// no harness, no relay to drive
|
||||
drive_relay = false;
|
||||
}
|
||||
|
||||
if(car_harness_status == HARNESS_STATUS_NORMAL){
|
||||
set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !intercept);
|
||||
} else {
|
||||
set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !intercept);
|
||||
}
|
||||
if (drive_relay) {
|
||||
harness.relay_driven = true;
|
||||
}
|
||||
|
||||
// wait until we're not reading the analog voltages anymore
|
||||
while (harness.sbu_adc_lock == true) {}
|
||||
|
||||
if (harness.status == HARNESS_STATUS_NORMAL) {
|
||||
set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, true);
|
||||
set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !drive_relay);
|
||||
} else {
|
||||
set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !drive_relay);
|
||||
set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, true);
|
||||
}
|
||||
|
||||
if (!drive_relay) {
|
||||
harness.relay_driven = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool harness_check_ignition(void) {
|
||||
bool ret = false;
|
||||
switch(car_harness_status){
|
||||
|
||||
// wait until we're not reading the analog voltages anymore
|
||||
while (harness.sbu_adc_lock == true) {}
|
||||
|
||||
switch(harness.status){
|
||||
case HARNESS_STATUS_NORMAL:
|
||||
ret = !get_gpio_input(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1);
|
||||
break;
|
||||
@@ -50,27 +72,46 @@ bool harness_check_ignition(void) {
|
||||
}
|
||||
|
||||
uint8_t harness_detect_orientation(void) {
|
||||
uint8_t ret = HARNESS_STATUS_NC;
|
||||
uint8_t ret = harness.status;
|
||||
|
||||
#ifndef BOOTSTUB
|
||||
uint32_t sbu1_voltage = adc_get_raw(current_board->harness_config->adc_channel_SBU1);
|
||||
uint32_t sbu2_voltage = adc_get_raw(current_board->harness_config->adc_channel_SBU2);
|
||||
// We can't detect orientation if the relay is being driven
|
||||
if (!harness.relay_driven && current_board->harness_config->has_harness) {
|
||||
harness.sbu_adc_lock = true;
|
||||
set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_ANALOG);
|
||||
set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_ANALOG);
|
||||
|
||||
// Detect connection and orientation
|
||||
if((sbu1_voltage < HARNESS_CONNECTED_THRESHOLD) || (sbu2_voltage < HARNESS_CONNECTED_THRESHOLD)){
|
||||
if (sbu1_voltage < sbu2_voltage) {
|
||||
// orientation flipped (PANDA_SBU1->HARNESS_SBU1(relay), PANDA_SBU2->HARNESS_SBU2(ign))
|
||||
ret = HARNESS_STATUS_FLIPPED;
|
||||
harness.sbu1_voltage_mV = adc_get_mV(current_board->harness_config->adc_channel_SBU1);
|
||||
harness.sbu2_voltage_mV = adc_get_mV(current_board->harness_config->adc_channel_SBU2);
|
||||
uint16_t detection_threshold = current_board->avdd_mV / 2U;
|
||||
|
||||
// Detect connection and orientation
|
||||
if((harness.sbu1_voltage_mV < detection_threshold) || (harness.sbu2_voltage_mV < detection_threshold)){
|
||||
if (harness.sbu1_voltage_mV < harness.sbu2_voltage_mV) {
|
||||
// orientation flipped (PANDA_SBU1->HARNESS_SBU1(relay), PANDA_SBU2->HARNESS_SBU2(ign))
|
||||
ret = HARNESS_STATUS_FLIPPED;
|
||||
} else {
|
||||
// orientation normal (PANDA_SBU2->HARNESS_SBU1(relay), PANDA_SBU1->HARNESS_SBU2(ign))
|
||||
ret = HARNESS_STATUS_NORMAL;
|
||||
}
|
||||
} else {
|
||||
// orientation normal (PANDA_SBU2->HARNESS_SBU1(relay), PANDA_SBU1->HARNESS_SBU2(ign))
|
||||
ret = HARNESS_STATUS_NORMAL;
|
||||
ret = HARNESS_STATUS_NC;
|
||||
}
|
||||
|
||||
// Pins are not 5V tolerant in ADC mode
|
||||
set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_INPUT);
|
||||
set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_INPUT);
|
||||
harness.sbu_adc_lock = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void harness_tick(void) {
|
||||
harness.status = harness_detect_orientation();
|
||||
}
|
||||
|
||||
void harness_init(void) {
|
||||
// delay such that the connection is fully made before trying orientation detection
|
||||
current_board->set_led(LED_BLUE, true);
|
||||
@@ -78,18 +119,13 @@ void harness_init(void) {
|
||||
current_board->set_led(LED_BLUE, false);
|
||||
|
||||
// try to detect orientation
|
||||
uint8_t ret = harness_detect_orientation();
|
||||
if (ret != HARNESS_STATUS_NC) {
|
||||
print("detected car harness with orientation "); puth2(ret); print("\n");
|
||||
car_harness_status = ret;
|
||||
|
||||
// set the SBU lines to be inputs before using the relay. The lines are not 5V tolerant in ADC mode!
|
||||
set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_INPUT);
|
||||
set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_INPUT);
|
||||
|
||||
// keep busses connected by default
|
||||
set_intercept_relay(false);
|
||||
harness.status = harness_detect_orientation();
|
||||
if (harness.status != HARNESS_STATUS_NC) {
|
||||
print("detected car harness with orientation "); puth2(harness.status); print("\n");
|
||||
} else {
|
||||
print("failed to detect car harness!\n");
|
||||
}
|
||||
|
||||
// keep buses connected by default
|
||||
set_intercept_relay(false);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// When changing these structs, python/__init__.py needs to be kept up to date!
|
||||
|
||||
#define HEALTH_PACKET_VERSION 13
|
||||
#define HEALTH_PACKET_VERSION 14
|
||||
struct __attribute__((packed)) health_t {
|
||||
uint32_t uptime_pkt;
|
||||
uint32_t voltage_pkt;
|
||||
@@ -27,6 +27,8 @@ struct __attribute__((packed)) health_t {
|
||||
uint8_t safety_rx_checks_invalid;
|
||||
uint16_t spi_checksum_error_count;
|
||||
uint8_t fan_stall_count;
|
||||
uint16_t sbu1_voltage_mV;
|
||||
uint16_t sbu2_voltage_mV;
|
||||
};
|
||||
|
||||
#define CAN_HEALTH_PACKET_VERSION 4
|
||||
|
||||
@@ -144,6 +144,7 @@ void __attribute__ ((noinline)) enable_fpu(void) {
|
||||
|
||||
// called at 8Hz
|
||||
uint8_t loop_counter = 0U;
|
||||
uint8_t previous_harness_status = HARNESS_STATUS_NC;
|
||||
void tick_handler(void) {
|
||||
if (TICK_TIMER->SR != 0) {
|
||||
// siren
|
||||
@@ -180,8 +181,11 @@ void tick_handler(void) {
|
||||
current_board->set_led(LED_BLUE, (uptime_cnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
|
||||
|
||||
// tick drivers at 1Hz
|
||||
harness_tick();
|
||||
|
||||
const bool recent_heartbeat = heartbeat_counter == 0U;
|
||||
current_board->board_tick(check_started(), usb_enumerated, recent_heartbeat);
|
||||
current_board->board_tick(check_started(), usb_enumerated, recent_heartbeat, ((harness.status != previous_harness_status) && (harness.status != HARNESS_STATUS_NC)));
|
||||
previous_harness_status = harness.status;
|
||||
|
||||
// increase heartbeat counter and cap it at the uint32 limit
|
||||
if (heartbeat_counter < __UINT32_MAX__) {
|
||||
|
||||
@@ -23,7 +23,7 @@ int get_health_pkt(void *dat) {
|
||||
health->tx_buffer_overflow_pkt = tx_buffer_overflow;
|
||||
health->rx_buffer_overflow_pkt = rx_buffer_overflow;
|
||||
health->gmlan_send_errs_pkt = gmlan_send_errs;
|
||||
health->car_harness_status_pkt = car_harness_status;
|
||||
health->car_harness_status_pkt = harness.status;
|
||||
health->safety_mode_pkt = (uint8_t)(current_safety_mode);
|
||||
health->safety_param_pkt = current_safety_param;
|
||||
health->alternative_experience_pkt = alternative_experience;
|
||||
@@ -41,6 +41,9 @@ int get_health_pkt(void *dat) {
|
||||
health->fan_power = fan_state.power;
|
||||
health->fan_stall_count = fan_state.total_stall_count;
|
||||
|
||||
health->sbu1_voltage_mV = harness.sbu1_voltage_mV;
|
||||
health->sbu2_voltage_mV = harness.sbu2_voltage_mV;
|
||||
|
||||
return sizeof(*health);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ void EXTI_IRQ_Handler(void);
|
||||
|
||||
void exti_irq_init(void) {
|
||||
SYSCFG->EXTICR[2] &= ~(SYSCFG_EXTICR3_EXTI8_Msk);
|
||||
if (car_harness_status == HARNESS_STATUS_FLIPPED) {
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
// CAN2_RX
|
||||
current_board->enable_can_transceiver(3U, false);
|
||||
SYSCFG->EXTICR[2] |= (SYSCFG_EXTICR3_EXTI8_PA);
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
|
||||
#define MAX_LED_FADE 8192U
|
||||
|
||||
// Threshold voltage (mV) for either of the SBUs to be below before deciding harness is connected
|
||||
#define HARNESS_CONNECTED_THRESHOLD 2500U
|
||||
|
||||
#define NUM_INTERRUPTS 102U // There are 102 external interrupt sources (see stm32f413.h)
|
||||
|
||||
#define TICK_TIMER_IRQ TIM1_BRK_TIM9_IRQn
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
void EXTI_IRQ_Handler(void);
|
||||
|
||||
void exti_irq_init(void) {
|
||||
if (car_harness_status == HARNESS_STATUS_FLIPPED) {
|
||||
if (harness.status == HARNESS_STATUS_FLIPPED) {
|
||||
// CAN2_RX IRQ on falling edge (EXTI10)
|
||||
current_board->enable_can_transceiver(3U, false);
|
||||
SYSCFG->EXTICR[2] &= ~(SYSCFG_EXTICR3_EXTI10_Msk);
|
||||
|
||||
@@ -30,9 +30,6 @@ separate IRQs for RX and TX.
|
||||
|
||||
#define MAX_LED_FADE 10240U
|
||||
|
||||
// Threshold voltage (mV) for either of the SBUs to be below before deciding harness is connected
|
||||
#define HARNESS_CONNECTED_THRESHOLD 40000U
|
||||
|
||||
// There are 163 external interrupt sources (see stm32f735xx.h)
|
||||
#define NUM_INTERRUPTS 163U
|
||||
|
||||
|
||||
@@ -182,9 +182,9 @@ class Panda:
|
||||
HW_TYPE_TRES = b'\x09'
|
||||
|
||||
CAN_PACKET_VERSION = 4
|
||||
HEALTH_PACKET_VERSION = 13
|
||||
HEALTH_PACKET_VERSION = 14
|
||||
CAN_HEALTH_PACKET_VERSION = 4
|
||||
HEALTH_STRUCT = struct.Struct("<IIIIIIIIIBBBBBBHBBBHfBBHB")
|
||||
HEALTH_STRUCT = struct.Struct("<IIIIIIIIIBBBBBBHBBBHfBBHBHH")
|
||||
CAN_HEALTH_STRUCT = struct.Struct("<BIBBBBBBBBIIIIIIIHHBBB")
|
||||
|
||||
F2_DEVICES = (HW_TYPE_PEDAL, )
|
||||
@@ -200,6 +200,10 @@ class Panda:
|
||||
HW_TYPE_TRES: 6600,
|
||||
}
|
||||
|
||||
HARNESS_STATUS_NC = 0
|
||||
HARNESS_STATUS_NORMAL = 1
|
||||
HARNESS_STATUS_FLIPPED = 2
|
||||
|
||||
# first byte is for EPS scaling factor
|
||||
FLAG_TOYOTA_ALT_BRAKE = (1 << 8)
|
||||
FLAG_TOYOTA_STOCK_LONGITUDINAL = (2 << 8)
|
||||
@@ -566,6 +570,8 @@ class Panda:
|
||||
"safety_rx_checks_invalid": a[22],
|
||||
"spi_checksum_error_count": a[23],
|
||||
"fan_stall_count": a[24],
|
||||
"sbu1_voltage_mV": a[25],
|
||||
"sbu2_voltage_mV": a[26],
|
||||
}
|
||||
|
||||
@ensure_can_health_packet_version
|
||||
|
||||
@@ -18,17 +18,51 @@ def test_ignition(p, panda_jungle):
|
||||
|
||||
|
||||
@pytest.mark.test_panda_types(PandaGroup.GEN2)
|
||||
def test_orientation_detection(p, panda_jungle):
|
||||
seen_orientations = []
|
||||
for i in range(3):
|
||||
panda_jungle.set_harness_orientation(i)
|
||||
p.reset()
|
||||
def test_harness_status(p, panda_jungle):
|
||||
flipped = None
|
||||
for ignition in [True, False]:
|
||||
for orientation in [Panda.HARNESS_STATUS_NC, Panda.HARNESS_STATUS_NORMAL, Panda.HARNESS_STATUS_FLIPPED]:
|
||||
panda_jungle.set_harness_orientation(orientation)
|
||||
panda_jungle.set_ignition(ignition)
|
||||
time.sleep(1)
|
||||
|
||||
health = p.health()
|
||||
detected_orientation = health['car_harness_status']
|
||||
print(f"set: {orientation} detected: {detected_orientation}")
|
||||
|
||||
# Orientation
|
||||
if orientation == Panda.HARNESS_STATUS_NC:
|
||||
assert detected_orientation == Panda.HARNESS_STATUS_NC
|
||||
else:
|
||||
if flipped is None:
|
||||
flipped = (detected_orientation != orientation)
|
||||
|
||||
if orientation == Panda.HARNESS_STATUS_NORMAL:
|
||||
assert detected_orientation == (Panda.HARNESS_STATUS_FLIPPED if flipped else Panda.HARNESS_STATUS_NORMAL)
|
||||
else:
|
||||
assert detected_orientation == (Panda.HARNESS_STATUS_NORMAL if flipped else Panda.HARNESS_STATUS_FLIPPED)
|
||||
|
||||
# Line ignition
|
||||
assert health['ignition_line'] == (False if orientation == Panda.HARNESS_STATUS_NC else ignition)
|
||||
|
||||
# SBU voltages
|
||||
supply_voltage_mV = 1800 if p.get_type() in [Panda.HW_TYPE_TRES, ] else 3300
|
||||
|
||||
if orientation == Panda.HARNESS_STATUS_NC:
|
||||
assert health['sbu1_voltage_mV'] > 0.9 * supply_voltage_mV
|
||||
assert health['sbu2_voltage_mV'] > 0.9 * supply_voltage_mV
|
||||
else:
|
||||
relay_line = 'sbu1_voltage_mV' if (detected_orientation == Panda.HARNESS_STATUS_FLIPPED) else 'sbu2_voltage_mV'
|
||||
ignition_line = 'sbu2_voltage_mV' if (detected_orientation == Panda.HARNESS_STATUS_FLIPPED) else 'sbu1_voltage_mV'
|
||||
|
||||
assert health[relay_line] < 0.1 * supply_voltage_mV
|
||||
assert health[ignition_line] > health[relay_line]
|
||||
if ignition:
|
||||
assert health[ignition_line] < 0.3 * supply_voltage_mV
|
||||
else:
|
||||
assert health[ignition_line] > 0.9 * supply_voltage_mV
|
||||
|
||||
|
||||
detected_harness_orientation = p.health()['car_harness_status']
|
||||
print(f"Detected orientation: {detected_harness_orientation}")
|
||||
if (i == 0 and detected_harness_orientation != 0) or detected_harness_orientation in seen_orientations:
|
||||
assert False
|
||||
seen_orientations.append(detected_harness_orientation)
|
||||
|
||||
@pytest.mark.skip_panda_types((Panda.HW_TYPE_DOS, ))
|
||||
def test_voltage(p):
|
||||
|
||||
Reference in New Issue
Block a user