diff --git a/VERSION b/VERSION index 0408c30b42460f..24e56e03c0da59 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.2.0 \ No newline at end of file +v1.2.1 \ No newline at end of file diff --git a/board/drivers/can.h b/board/drivers/can.h index e1604c2cf244de..9f02c2eba74d2d 100644 --- a/board/drivers/can.h +++ b/board/drivers/can.h @@ -3,6 +3,8 @@ #define ALL_CAN_BUT_MAIN_SILENT 0xFE #define ALL_CAN_LIVE 0 +#include "lline_relay.h" + int can_live = 0, pending_can_live = 0, can_loopback = 0, can_silent = ALL_CAN_SILENT; // ********************* instantiate queues ********************* @@ -453,14 +455,16 @@ void can_rx(uint8_t can_number) { // forwarding (panda only) #ifdef PANDA - int bus_fwd_num = can_forwarding[bus_number] != -1 ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push); - if (bus_fwd_num != -1) { - CAN_FIFOMailBox_TypeDef to_send; - to_send.RIR = to_push.RIR | 1; // TXRQ - to_send.RDTR = to_push.RDTR; - to_send.RDLR = to_push.RDLR; - to_send.RDHR = to_push.RDHR; - can_send(&to_send, bus_fwd_num); + if ((get_lline_status() != 0) || !relay_control) { //Relay engaged or relay isn't controlled, allow fwd + int bus_fwd_num = can_forwarding[bus_number] != -1 ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push); + if (bus_fwd_num != -1) { + CAN_FIFOMailBox_TypeDef to_send; + to_send.RIR = to_push.RIR | 1; // TXRQ + to_send.RDTR = to_push.RDTR; + to_send.RDLR = to_push.RDLR; + to_send.RDHR = to_push.RDHR; + can_send(&to_send, bus_fwd_num); + } } #endif diff --git a/board/drivers/lline_relay.h b/board/drivers/lline_relay.h new file mode 100644 index 00000000000000..217e7dfe3006bf --- /dev/null +++ b/board/drivers/lline_relay.h @@ -0,0 +1,88 @@ +#ifdef PANDA + +int relay_control = 0; // True if relay is controlled through l-line + +/* Conrol a relay connected to l-line pin */ + +// 160us cycles, 1 high, 25 low + +volatile int turn_on_relay = 0; +volatile int on_cycles = 25; + +//5s timeout +#define LLINE_TIMEOUT_CYCLES 31250 +volatile int timeout_cycles = LLINE_TIMEOUT_CYCLES; + +void TIM5_IRQHandler(void) { + if (TIM5->SR & TIM_SR_UIF) { + on_cycles--; + timeout_cycles--; + if (timeout_cycles == 0) { + turn_on_relay = 0; + } + if (on_cycles > 0) { + if (turn_on_relay) { + set_gpio_output(GPIOC, 10, 0); + } + } + else { + set_gpio_output(GPIOC, 10, 1); + on_cycles = 25; + } + } + TIM5->ARR = 160-1; + TIM5->SR = 0; +} + +void lline_relay_init (void) { + set_lline_output(0); + relay_control = 1; + set_gpio_output(GPIOC, 10, 1); + + // setup + TIM5->PSC = 48-1; // tick on 1 us + TIM5->CR1 = TIM_CR1_CEN; // enable + TIM5->ARR = 50-1; // 50 us + TIM5->DIER = TIM_DIER_UIE; // update interrupt + TIM5->CNT = 0; + + NVIC_EnableIRQ(TIM5_IRQn); + +#ifdef DEBUG + puts("INIT LLINE\n"); + puts(" SR "); + putui(TIM5->SR); + puts(" PSC "); + putui(TIM5->PSC); + puts(" CR1 "); + putui(TIM5->CR1); + puts(" ARR "); + putui(TIM5->ARR); + puts(" DIER "); + putui(TIM5->DIER); + puts(" SR "); + putui(TIM5->SR); + puts(" CNT "); + putui(TIM5->CNT); + puts("\n"); +#endif +} + +void lline_relay_release (void) { + set_lline_output(0); + relay_control = 0; + puts("RELEASE LLINE\n"); + set_gpio_alternate(GPIOC, 10, GPIO_AF7_USART3); + NVIC_DisableIRQ(TIM5_IRQn); +} + +void set_lline_output(int to_set) { + timeout_cycles = LLINE_TIMEOUT_CYCLES; + turn_on_relay = to_set; +} + +int get_lline_status() { + return turn_on_relay; +} + +#endif diff --git a/board/gpio.h b/board/gpio.h index 061adf49f357a2..ede6c9b3e929c0 100644 --- a/board/gpio.h +++ b/board/gpio.h @@ -120,6 +120,7 @@ void periph_init() { RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; + RCC->APB1ENR |= RCC_APB1ENR_TIM5EN; RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN; RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN; @@ -391,7 +392,9 @@ void gpio_init() { set_gpio_output(GPIOA, 14, 1); // C10,C11: L-Line setup on USART 3 - set_gpio_alternate(GPIOC, 10, GPIO_AF7_USART3); + // LLine now used for relay output + set_gpio_output(GPIOC, 10, 1); + //set_gpio_alternate(GPIOC, 10, GPIO_AF7_USART3); set_gpio_alternate(GPIOC, 11, GPIO_AF7_USART3); set_gpio_pullup(GPIOC, 11, PULL_UP); #endif diff --git a/board/main.c b/board/main.c index 248fdea68c0cb4..478f8b9423f787 100644 --- a/board/main.c +++ b/board/main.c @@ -163,6 +163,14 @@ void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) { uint8_t bus_number = (to_push.RDTR >> 4) & CAN_BUS_NUM_MASK; can_send(&to_push, bus_number); + + #ifdef PANDA + // Enable relay on can message if allowed. + // Temporary until OP has support for relay + if (safety_relay_hook()) { + set_lline_output(1); + } + #endif } } @@ -444,6 +452,16 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { } break; } + // **** 0xf3: set l-line relay + case 0xf3: + { + #ifdef PANDA + if (safety_relay_hook()) { + set_lline_output(setup->b.wValue.w == 1); + } + #endif + break; + } default: puts("NO HANDLER "); puth(setup->b.bRequest); diff --git a/board/safety.h b/board/safety.h index 6e5dc8e36f62b2..5543333e3a6cb0 100644 --- a/board/safety.h +++ b/board/safety.h @@ -29,6 +29,10 @@ int driver_limit_check(int val, int val_last, struct sample_t *val_driver, int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA); #ifdef PANDA float interpolate(struct lookup_t xy, float x); + +void lline_relay_init (void); +void lline_relay_release (void); +void set_lline_output(int to_set); #endif typedef void (*safety_hook_init)(int16_t param); @@ -37,6 +41,7 @@ typedef int (*tx_hook)(CAN_FIFOMailBox_TypeDef *to_send); typedef int (*tx_lin_hook)(int lin_num, uint8_t *data, int len); typedef int (*ign_hook)(); typedef int (*fwd_hook)(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd); +typedef int (*relay_hook)(); typedef struct { safety_hook_init init; @@ -45,6 +50,7 @@ typedef struct { tx_hook tx; tx_lin_hook tx_lin; fwd_hook fwd; + relay_hook relay; } safety_hooks; // This can be set by the safety hooks. @@ -91,6 +97,10 @@ int safety_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { return current_hooks->fwd(bus_num, to_fwd); } +int safety_relay_hook(void) { + return current_hooks->relay(); +} + typedef struct { uint16_t id; const safety_hooks *hooks; diff --git a/board/safety/safety_cadillac.h b/board/safety/safety_cadillac.h index 2a2d8b9857ff91..0e6636a1a0764d 100644 --- a/board/safety/safety_cadillac.h +++ b/board/safety/safety_cadillac.h @@ -115,6 +115,9 @@ static int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { static void cadillac_init(int16_t param) { controls_allowed = 0; cadillac_ign = 0; + #ifdef PANDA + lline_relay_release(); + #endif } static int cadillac_ign_hook() { @@ -128,4 +131,5 @@ const safety_hooks cadillac_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = cadillac_ign_hook, .fwd = alloutput_fwd_hook, + .relay = nooutput_relay_hook, }; diff --git a/board/safety/safety_chrysler.h b/board/safety/safety_chrysler.h index 4af588401e0ec0..a8826b9154e80d 100644 --- a/board/safety/safety_chrysler.h +++ b/board/safety/safety_chrysler.h @@ -127,6 +127,9 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { static void chrysler_init(int16_t param) { chrysler_camera_detected = 0; + #ifdef PANDA + lline_relay_release(); + #endif } static int chrysler_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { @@ -150,4 +153,5 @@ const safety_hooks chrysler_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = chrysler_fwd_hook, + .relay = nooutput_relay_hook, }; diff --git a/board/safety/safety_defaults.h b/board/safety/safety_defaults.h index 196df65d2f8eb6..88d31a7de57b48 100644 --- a/board/safety/safety_defaults.h +++ b/board/safety/safety_defaults.h @@ -8,6 +8,9 @@ int default_ign_hook() { static void nooutput_init(int16_t param) { controls_allowed = 0; + #ifdef PANDA + lline_relay_release(); + #endif } static int nooutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { @@ -22,6 +25,10 @@ static int nooutput_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { return -1; } +static int nooutput_relay_hook(int to_set) { + return false; +} + const safety_hooks nooutput_hooks = { .init = nooutput_init, .rx = default_rx_hook, @@ -29,12 +36,16 @@ const safety_hooks nooutput_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = nooutput_fwd_hook, + .relay = nooutput_relay_hook, }; // *** all output safety mode *** static void alloutput_init(int16_t param) { controls_allowed = 1; + #ifdef PANDA + lline_relay_release(); + #endif } static int alloutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { @@ -49,6 +60,10 @@ static int alloutput_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { return -1; } +static int alloutput_relay_hook(int to_set) { + return true; +} + const safety_hooks alloutput_hooks = { .init = alloutput_init, .rx = default_rx_hook, @@ -56,4 +71,5 @@ const safety_hooks alloutput_hooks = { .tx_lin = alloutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = alloutput_fwd_hook, + .relay = alloutput_relay_hook, }; diff --git a/board/safety/safety_elm327.h b/board/safety/safety_elm327.h index 98dce6532ac8ba..e89783bcca6d44 100644 --- a/board/safety/safety_elm327.h +++ b/board/safety/safety_elm327.h @@ -42,4 +42,5 @@ const safety_hooks elm327_hooks = { .tx_lin = elm327_tx_lin_hook, .ignition = default_ign_hook, .fwd = elm327_fwd_hook, + .relay = nooutput_relay_hook, }; diff --git a/board/safety/safety_ford.h b/board/safety/safety_ford.h index 075029fb623e0f..1d3f16d0694676 100644 --- a/board/safety/safety_ford.h +++ b/board/safety/safety_ford.h @@ -90,4 +90,5 @@ const safety_hooks ford_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = nooutput_fwd_hook, + .relay = nooutput_relay_hook, }; diff --git a/board/safety/safety_gm.h b/board/safety/safety_gm.h index f35b26b4ef84d3..396fb8770c36f4 100644 --- a/board/safety/safety_gm.h +++ b/board/safety/safety_gm.h @@ -228,6 +228,9 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { static void gm_init(int16_t param) { controls_allowed = 0; gm_ignition_started = 0; + #ifdef PANDA + lline_relay_release(); + #endif } static int gm_ign_hook() { @@ -241,5 +244,5 @@ const safety_hooks gm_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = gm_ign_hook, .fwd = nooutput_fwd_hook, + .relay = nooutput_relay_hook, }; - diff --git a/board/safety/safety_gm_ascm.h b/board/safety/safety_gm_ascm.h index 70a042ec514a69..b145466d9de225 100644 --- a/board/safety/safety_gm_ascm.h +++ b/board/safety/safety_gm_ascm.h @@ -48,5 +48,6 @@ const safety_hooks gm_ascm_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = gm_ascm_fwd_hook, + .relay = nooutput_relay_hook, }; diff --git a/board/safety/safety_honda.h b/board/safety/safety_honda.h index fbee6cfe861f53..40c6917b0b4c43 100644 --- a/board/safety/safety_honda.h +++ b/board/safety/safety_honda.h @@ -136,6 +136,9 @@ static void honda_init(int16_t param) { controls_allowed = 0; bosch_hardware = false; honda_alt_brake_msg = false; + #ifdef PANDA + lline_relay_release(); + #endif } static void honda_bosch_init(int16_t param) { @@ -143,6 +146,9 @@ static void honda_bosch_init(int16_t param) { bosch_hardware = true; // Checking for alternate brake override from safety parameter honda_alt_brake_msg = param == 1 ? true : false; + #ifdef PANDA + lline_relay_release(); + #endif } static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { @@ -176,6 +182,7 @@ const safety_hooks honda_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = honda_fwd_hook, + .relay = nooutput_relay_hook, }; const safety_hooks honda_bosch_hooks = { @@ -185,4 +192,5 @@ const safety_hooks honda_bosch_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = honda_bosch_fwd_hook, + .relay = nooutput_relay_hook, }; diff --git a/board/safety/safety_hyundai.h b/board/safety/safety_hyundai.h index b67632141d8365..9470e34d1556bd 100644 --- a/board/safety/safety_hyundai.h +++ b/board/safety/safety_hyundai.h @@ -152,6 +152,9 @@ static int hyundai_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { static void hyundai_init(int16_t param) { controls_allowed = 0; hyundai_giraffe_switch_2 = 0; + #ifdef PANDA + lline_relay_release(); + #endif } const safety_hooks hyundai_hooks = { @@ -161,4 +164,5 @@ const safety_hooks hyundai_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = hyundai_fwd_hook, + .relay = nooutput_relay_hook, }; diff --git a/board/safety/safety_subaru.h b/board/safety/safety_subaru.h index 00fe1abf91d2f7..8bc6b560c70622 100644 --- a/board/safety/safety_subaru.h +++ b/board/safety/safety_subaru.h @@ -14,6 +14,11 @@ int subaru_desired_torque_last = 0; uint32_t subaru_ts_last = 0; struct sample_t subaru_torque_driver; // last few driver torques measured +static void subaru_init(int16_t param) { + #ifdef PANDA + lline_relay_init(); + #endif +} static void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { int bus_number = (to_push->RDTR >> 4) & 0xFF; @@ -122,10 +127,11 @@ static int subaru_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { } const safety_hooks subaru_hooks = { - .init = nooutput_init, + .init = subaru_init, .rx = subaru_rx_hook, .tx = subaru_tx_hook, .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = subaru_fwd_hook, + .relay = alloutput_relay_hook, }; diff --git a/board/safety/safety_tesla.h b/board/safety/safety_tesla.h index 78c450e85e31c6..882a509f56105e 100644 --- a/board/safety/safety_tesla.h +++ b/board/safety/safety_tesla.h @@ -230,6 +230,9 @@ static void tesla_init(int16_t param) controls_allowed = 0; tesla_ignition_started = 0; gmlan_switch_init(1); //init the gmlan switch with 1s timeout enabled + #ifdef PANDA + lline_relay_release(); + #endif } static int tesla_ign_hook() @@ -284,4 +287,5 @@ const safety_hooks tesla_hooks = { .tx_lin = tesla_tx_lin_hook, .ignition = tesla_ign_hook, .fwd = tesla_fwd_hook, + .relay = nooutput_relay_hook, }; diff --git a/board/safety/safety_toyota.h b/board/safety/safety_toyota.h index 50d457ab69c6c7..02fcb36e5d6f83 100644 --- a/board/safety/safety_toyota.h +++ b/board/safety/safety_toyota.h @@ -160,6 +160,9 @@ static void toyota_init(int16_t param) { toyota_giraffe_switch_1 = 0; toyota_camera_forwarded = 0; toyota_dbc_eps_torque_factor = param; + #ifdef PANDA + lline_relay_release(); + #endif } static int toyota_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { @@ -181,6 +184,7 @@ const safety_hooks toyota_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = toyota_fwd_hook, + .relay = nooutput_relay_hook, }; static void toyota_nolimits_init(int16_t param) { @@ -189,6 +193,9 @@ static void toyota_nolimits_init(int16_t param) { toyota_giraffe_switch_1 = 0; toyota_camera_forwarded = 0; toyota_dbc_eps_torque_factor = param; + #ifdef PANDA + lline_relay_release(); + #endif } const safety_hooks toyota_nolimits_hooks = { @@ -198,4 +205,5 @@ const safety_hooks toyota_nolimits_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = toyota_fwd_hook, + .relay = nooutput_relay_hook, }; diff --git a/board/safety/safety_toyota_ipas.h b/board/safety/safety_toyota_ipas.h index ff4158e3c77c3b..13e664c0f9d88e 100644 --- a/board/safety/safety_toyota_ipas.h +++ b/board/safety/safety_toyota_ipas.h @@ -152,5 +152,5 @@ const safety_hooks toyota_ipas_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = toyota_fwd_hook, + .relay = nooutput_relay_hook, }; - diff --git a/python/__init__.py b/python/__init__.py index bfca642e8256f7..8c0bc5a9a2ae2d 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -392,6 +392,9 @@ def set_gmlan(self, bus=2): elif bus in [Panda.GMLAN_CAN2, Panda.GMLAN_CAN3]: self._handle.controlWrite(Panda.REQUEST_OUT, 0xdb, 1, bus, b'') + def set_lline_relay(self, enable): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf3, int(enable), 0, b'') + def set_can_loopback(self, enable): # set can loopback mode for all buses self._handle.controlWrite(Panda.REQUEST_OUT, 0xe5, int(enable), 0, b'') diff --git a/tests/safety/test.c b/tests/safety/test.c index 9b4c807d72d3f7..04e6576fb8072c 100644 --- a/tests/safety/test.c +++ b/tests/safety/test.c @@ -246,3 +246,12 @@ void reset_gmlan_switch_timeout(void){ void gmlan_switch_init(int timeout_enable){ } + +void lline_relay_init (void) { +} + +void lline_relay_release (void) { +} + +void set_lline_output(int to_set) { +}