From 3cf59d6a8c7edd24a02919c20fb2a371f66d042d Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Tue, 2 Jan 2024 16:36:09 +0100 Subject: [PATCH] Add escc flag to the scons build args Add initial README for ESCC board This commit introduces a new README for the ESCC board detailing the pinout configurations and connections between the Molex connector and IONIQ harness and radar components. The documentation provides a clear, structured guide to assist with proper wiring and setup. Improving comments for clarity and explicitness IDE is behaving now. Wd don't need this hack anymore Add ESCC build option and refine ESCC specific code Introduce --escc option in SCons to conditionally build ESCC firmware. Update build_project to support CPPDEFINES and modify main.c to handle ESCC-specific safety modes and behaviors more cleanly. Remove unnecessary send_escc_msg calls in Hyundai safety code The updates in the code remove redundant send_escc_msg calls in the Hyundai safety code. We don't really need to send the FCA or AEB data through the ESCC packet because we don't block it at all. So we don't really need to "package" it anymore on the ESCC message Add send_escc_msg call in case blocks The send_escc_msg function is now called within the individual case blocks for SCC11, SCC12, and FCA11, enhancing code readability. Before, it was called on any message that the radar sends, but this strategy was inefficient as it was piggybacking on their frequencies. Refactor `escc_tx_hook` function in Hyundai safety code The commented-out `escc_tx_hook` function in Hyundai ESCC safety code has been refactored and is now in use again, replacing the formerly used `alloutput_tx_hook`. Debugging functionality has been preserved and conditions for when the function is unused have also been handled. The resulting code is now cleaner and more efficient. Add ESCC firmware and build files, and safety mode for Hyundai ESCC This commit introduces ESCC firmware and the corresponding build files. We have also defined a new safety mode for Hyundai ESCC. The necessary scripts for flashing and recovery have been added, alongside the gitignore file for the ESCC board. Additionally, we have implemented new message processing and forwarding logic to handle ESCC specific messages in main and safety files. --- SConscript | 26 ++++--- SConstruct | 4 ++ board/config.h | 1 + board/escc/.gitignore | 1 + board/escc/README.MD | 81 ++++++++++++++++++++++ board/escc/SConscript | 34 +++++++++ board/escc/flash.py | 18 +++++ board/escc/flash_can.sh | 8 +++ board/escc/recover.sh | 11 +++ board/main.c | 94 ++++++++++++++++++++++++- board/safety.h | 12 +++- board/safety/safety_hyundai_escc.h | 107 +++++++++++++++++++++++++++++ board/safety_sunnypilot_common.h | 64 +++++++++++++++++ tests/escc/enter_canloader.py | 32 +++++++++ 14 files changed, 481 insertions(+), 12 deletions(-) create mode 100644 board/escc/.gitignore create mode 100644 board/escc/README.MD create mode 100644 board/escc/SConscript create mode 100755 board/escc/flash.py create mode 100755 board/escc/flash_can.sh create mode 100755 board/escc/recover.sh create mode 100644 board/safety/safety_hyundai_escc.h create mode 100644 board/safety_sunnypilot_common.h create mode 100755 tests/escc/enter_canloader.py diff --git a/SConscript b/SConscript index f6501e88cc..1f5be8fcba 100644 --- a/SConscript +++ b/SConscript @@ -62,7 +62,9 @@ def to_c_uint32(x): return "{" + 'U,'.join(map(str, nums)) + "U}" -def build_project(project_name, project, extra_flags): +def build_project(project_name, project, extra_flags, cppdefines=None): + cppdefines = cppdefines or [] + print(f"{project_name} -> CPPDEFINES [{', '.join(cppdefines)}]") linkerscript_fn = File(project["LINKER_SCRIPT"]).srcnode().relpath flags = project["PROJECT_FLAGS"] + extra_flags + common_flags + [ @@ -101,6 +103,7 @@ def build_project(project_name, project, extra_flags): 'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf') }, tools=["default", "compilation_db"], + CPPDEFINES=cppdefines, ) startup = env.Object(f"obj/startup_{project_name}", project["STARTUP_FILE"]) @@ -179,12 +182,15 @@ with open("board/obj/cert.h", "w") as f: for cert in certs: f.write("\n".join(cert) + "\n") -# panda fw -SConscript('board/SConscript') - -# panda jungle fw -SConscript('board/jungle/SConscript') - -# test files -if GetOption('extras'): - SConscript('tests/libpanda/SConscript') +if not GetOption('escc'): # if we are building ESCC, we don't build anything else + # panda fw + SConscript('board/SConscript') + + # panda jungle fw + SConscript('board/jungle/SConscript') + + # test files + if GetOption('extras'): + SConscript('tests/libpanda/SConscript') +else: + SConscript('board/escc/SConscript') diff --git a/SConstruct b/SConstruct index 11ff21738e..5e5a100830 100644 --- a/SConstruct +++ b/SConstruct @@ -20,6 +20,10 @@ AddOption('--mutation', action='store_true', help='generate mutation-ready code') +AddOption('--escc', + action='store_true', + help='build escc firmware') + env = Environment( COMPILATIONDB_USE_ABSPATH=True, tools=["default", "compilation_db"], diff --git a/board/config.h b/board/config.h index 6fb95ada26..529cec5930 100644 --- a/board/config.h +++ b/board/config.h @@ -9,6 +9,7 @@ //#define DEBUG_FAULTS //#define DEBUG_COMMS //#define DEBUG_FAN +//#define DEBUG_CAN_LOOP #define CAN_INIT_TIMEOUT_MS 500U #define USBPACKET_MAX_SIZE 0x40U diff --git a/board/escc/.gitignore b/board/escc/.gitignore new file mode 100644 index 0000000000..94053f2925 --- /dev/null +++ b/board/escc/.gitignore @@ -0,0 +1 @@ +obj/* diff --git a/board/escc/README.MD b/board/escc/README.MD new file mode 100644 index 0000000000..6eea4ba81a --- /dev/null +++ b/board/escc/README.MD @@ -0,0 +1,81 @@ +## Documentation +[see more](https://github.com/sunnypilot/sunnypilot/blob/5d754169a6285e88e755ff9a592a851cb92b0abc/docs/escc/ESCC%20IONIQ%20PHEV%20Guide.md) + +### Detailed Connection List + +#### Molex 5018762640 Pinout: + +- Pin 1: GND +- Pin 2: IGN +- Pin 3: internal 120 Ohm Resistor, simply bridge to Pin 5 +- Pin 4: C-CAN HIGH +- Pin 5: internal 120 Ohm Resistor, simply bridge to Pin 3 +- Pin 6: C-CAN LOW +- Pin 8: L-CAN HIGH +- Pin 10: L-CAN LOW +- Pin 12: 12v +- Pin 14: 12v +- Pin 16: IGN +- Pin 18: L-CAN HIGH +- Pin 20: L-CAN LOW +- Pin 22: C-CAN HIGH +- Pin 24: C-CAN LOW +- Pin 26: GND + +#### **IONIQ 2203663 (Car Harness, Female):** + +- Pin 1: 12v -> Molex Pin 12 +- Pin 4: GND -> Molex Pin 1 +- Pin 7: C-CAN LOW -> Molex Pin 6 +- Pin 8: C-CAN HIGH -> Molex Pin 4 +- Pin 9: L-CAN LOW -> Molex Pin 10 +- Pin 10: IGPM (IGN) -> Molex Pin 2 +- Pin 18: L-CAN HIGH -> Molex Pin 8 + +#### **IONIQ 2203663 (Car Radar, Male):** + +- Molex Pin: 14 -> Pin 1: 12v +- Molex Pin: 26 -> Pin 4: GND +- Molex Pin: 24 -> Pin 7: C-CAN LOW +- Molex Pin: 22 -> Pin 8: C-CAN HIGH +- Molex Pin: 20 -> Pin 9: L-CAN LOW +- Molex Pin: 16 -> Pin 10: IGN +- Molex Pin: 18 -> Pin 18: L-CAN HIGH + + +``` +IONIQ 2203663 Molex 5018762640 IONIQ 2203663 +Car Harness (Female) Car Radar (Male) ++-----+-----+ +-----+-----+ +-----+-----+ +| 18 | 9 | | 2 | 1 | | 10 | 1 | +| 17 | 8 | | 4 | 3 | | 11 | 2 | +| 16 | 7 | | 6 | 5 | | 12 | 3 | +| 15 | 6 | | 8 | 7 | | 13 | 4 | +| 14 | 5 | NOTCH | 10 | 9 | | 14 | 5 | NOTCH +| 13 | 4 | | 12 | 11 | | 15 | 6 | +| 12 | 3 | | 14 | 13 | NOTCH | 16 | 7 | +| 11 | 2 | | 16 | 15 | | 17 | 8 | +| 10 | 1 | | 18 | 17 | | 18 | 9 | ++-----+-----+ | 20 | 19 | +-----+-----+ + | 22 | 21 | + | 24 | 23 | + | 26 | 25 | + +-----+-----+ + +Connections: +Molex Pin 3 (120 Ohm) <--> Molex Pin 5 (120 Ohm) +Harness Pin 1 (12V) <--> Molex Pin 12 (12V) +Harness Pin 4 (GND) <--> Molex Pin 1 (GND) +Harness Pin 10 (IGN) <--> Molex Pin 2 (IGN) +Harness Pin 8 (C-CAN H) <--> Molex Pin 4 (C-CAN H) +Harness Pin 7 (C-CAN L) <--> Molex Pin 6 (C-CAN L) +Harness Pin 18 (L-CAN H) <--> Molex Pin 8 (L-CAN H) +Harness Pin 9 (L-CAN L) <--> Molex Pin 10 (L-CAN L) + Molex Pin 20 (L-CAN L) <--> Radar Pin 9 (L-CAN L) + Molex Pin 18 (L-CAN H) <--> Radar Pin 18 (L-CAN H) + Molex Pin 24 (C-CAN L) <--> Radar Pin 7 (C-CAN L) + Molex Pin 22 (C-CAN H) <--> Radar Pin 8 (C-CAN H) + Molex Pin 16 (IGN) <--> Radar Pin 10 (IGN) + Molex Pin 14 (12V) <--> Radar Pin 1 (12V) + Molex Pin 26 (GND) <--> Radar Pin 4 (GND) +``` \ No newline at end of file diff --git a/board/escc/SConscript b/board/escc/SConscript new file mode 100644 index 0000000000..79a7c98e22 --- /dev/null +++ b/board/escc/SConscript @@ -0,0 +1,34 @@ +import os +import copy + +Import('build_project') + +build_projects = {} + +build_projects["escc"] = { + "MAIN": "../main.c", + "BOOTSTUB": "../bootstub.c", + "STARTUP_FILE": File("../stm32f4/startup_stm32f413xx.s"), + "LINKER_SCRIPT": File("../stm32f4/stm32f4_flash.ld"), + "APP_START_ADDRESS": "0x8004000", + "PROJECT_FLAGS": [ + "-mcpu=cortex-m4", + "-mhard-float", + "-DSTM32F4", + "-DSTM32F413xx", + "-mfpu=fpv4-sp-d16", + "-fsingle-precision-constant", + "-Os", + "-g", + ], +} + +for project_name, project in build_projects.items(): + flags = [ + "-DPANDA", + "-DESCC", + ] + if ("ENABLE_SPI" in os.environ or "h7" in project_name) and not project_name.startswith('pedal'): + flags.append('-DENABLE_SPI') + + build_project(project_name, project, flags, ["ESCC"]) diff --git a/board/escc/flash.py b/board/escc/flash.py new file mode 100755 index 0000000000..cc7e7212f6 --- /dev/null +++ b/board/escc/flash.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +import os +import subprocess + +from panda import Panda + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + print(board_path) + subprocess.check_call(f"scons -C {board_path}/../.. -j$(nproc) {board_path} --escc", shell=True) + + serials = Panda.list() + print(f"found {len(serials)} panda(s) - {serials}") + for s in serials: + print("flashing", s) + with Panda(serial=s) as p: + p.flash("obj/escc.bin.signed") diff --git a/board/escc/flash_can.sh b/board/escc/flash_can.sh new file mode 100755 index 0000000000..634f1acdd1 --- /dev/null +++ b/board/escc/flash_can.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env sh +set -e + +cd .. +scons -u -j$(nproc) --escc +cd escc + +../../tests/escc/enter_canloader.py obj/escc.bin.signed diff --git a/board/escc/recover.sh b/board/escc/recover.sh new file mode 100755 index 0000000000..6276742dac --- /dev/null +++ b/board/escc/recover.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -e + +DFU_UTIL="dfu-util" + +cd .. +scons -u -j$(nproc) --escc +cd escc + +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D obj/escc.bin.signed +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.escc.bin diff --git a/board/main.c b/board/main.c index 7c068113a0..45ff2554c5 100644 --- a/board/main.c +++ b/board/main.c @@ -124,6 +124,61 @@ bool is_car_safety_mode(uint16_t mode) { (mode != SAFETY_ELM327); } +#ifdef ESCC +// ***************************** ESCC code ***************************** +bool is_car_safety_mode_escc(uint16_t mode) { + return is_car_safety_mode(mode) && (mode != SAFETY_HYUNDAI_ESCC); +} +#define is_car_safety_mode is_car_safety_mode_escc + +#define CAN_ESCC_INPUT 0x2AC +#define CAN_ESCC_OUTPUT 0x2ABU + +void send_escc_msg(const ESCC_Msg *msg, const int bus_number) { +#ifdef DEBUG + + print("send_escc_msg\n"); + print("fca_cmd_act: "); putui(msg->fca_cmd_act); print("\n"); + print("aeb_cmd_act: "); putui(msg->aeb_cmd_act); print("\n"); + print("cf_vsm_warn_fca11: "); putui(msg->cf_vsm_warn_fca11); print("\n"); + print("cf_vsm_warn_scc12: "); putui(msg->cf_vsm_warn_scc12); print("\n"); + print("cf_vsm_deccmdact_scc12: "); putui(msg->cf_vsm_deccmdact_scc12); print("\n"); + print("cf_vsm_deccmdact_fca11: "); putui(msg->cf_vsm_deccmdact_fca11); print("\n"); + print("cr_vsm_deccmd_scc12: "); putui(msg->cr_vsm_deccmd_scc12); print("\n"); + print("cr_vsm_deccmd_fca11: "); putui(msg->cr_vsm_deccmd_fca11); print("\n"); + print("obj_valid: "); putui(msg->obj_valid); print("\n"); + print("acc_objstatus: "); putui(msg->acc_objstatus); print("\n"); + print("acc_obj_lat_pos_1: "); putui(msg->acc_obj_lat_pos_1); print("\n"); + print("acc_obj_lat_pos_2: "); putui(msg->acc_obj_lat_pos_2); print("\n"); + print("acc_obj_dist_1: "); putui(msg->acc_obj_dist_1); print("\n"); + print("acc_obj_dist_2: "); putui(msg->acc_obj_dist_2); print("\n"); + print("acc_obj_rel_spd_1: "); putui(msg->acc_obj_rel_spd_1); print("\n"); + print("acc_obj_rel_spd_2: "); putui(msg->acc_obj_rel_spd_2); print("\n"); +#endif + + uint8_t dat[8]; + dat[0] = (msg->fca_cmd_act) | (msg->cf_vsm_warn_fca11 << 1) | (msg->aeb_cmd_act << 3) | + (msg->cf_vsm_warn_scc12 << 4) | (msg->cf_vsm_deccmdact_scc12 << 6) | (msg->cf_vsm_deccmdact_fca11 << 7); + dat[1] = (msg->cr_vsm_deccmd_scc12); + dat[2] = (msg->obj_valid) | (msg->acc_objstatus << 1); + dat[3] = (msg->acc_obj_lat_pos_1); + dat[4] = (msg->acc_obj_lat_pos_2) | (msg->acc_obj_dist_1 << 1); + dat[5] = (msg->acc_obj_dist_2) | (msg->acc_obj_rel_spd_1 << 4); + dat[6] = (msg->acc_obj_rel_spd_2); + dat[7] = (msg->cr_vsm_deccmd_fca11); + + CANPacket_t to_send; + to_send.extended = CAN_ESCC_OUTPUT >= 0x800 ? 1 : 0; + to_send.addr = CAN_ESCC_OUTPUT; + to_send.bus = bus_number; + to_send.data_len_code = sizeof(dat); + memcpy(to_send.data, dat, sizeof(dat)); + + can_set_checksum(&to_send); + can_send(&to_send, bus_number, true); +} +#endif + // ***************************** main code ***************************** // cppcheck-suppress unusedFunction ; used in headers not included in cppcheck @@ -186,7 +241,9 @@ static void tick_handler(void) { print("rx:"); puth4(can_rx_q.r_ptr); print("-"); puth4(can_rx_q.w_ptr); print(" "); print("tx1:"); puth4(can_tx1_q.r_ptr); print("-"); puth4(can_tx1_q.w_ptr); print(" "); print("tx2:"); puth4(can_tx2_q.r_ptr); print("-"); puth4(can_tx2_q.w_ptr); print(" "); - print("tx3:"); puth4(can_tx3_q.r_ptr); print("-"); puth4(can_tx3_q.w_ptr); print("\n"); + print("tx3:"); puth4(can_tx3_q.r_ptr); print("-"); puth4(can_tx3_q.w_ptr); print(" "); + print("SAFETY MODE:"); putui(current_safety_mode); + print("\n"); #endif // set green LED to be controls allowed @@ -235,6 +292,7 @@ static void tick_handler(void) { mads_heartbeat_engaged_check(); +#ifndef ESCC // Hearbet disabled when ESCC if (!heartbeat_disabled) { // if the heartbeat has been gone for a while, go to SILENT safety mode and enter power save if (heartbeat_counter >= (check_started() ? HEARTBEAT_IGNITION_CNT_ON : HEARTBEAT_IGNITION_CNT_OFF)) { @@ -273,6 +331,7 @@ static void tick_handler(void) { fan_set_power(enabled ? 50U : 0U); } } +#endif // check registers check_registers(); @@ -335,8 +394,13 @@ int main(void) { fan_init(); } +#ifdef ESCC + // init to SAFETY_HYUNDAI_ESCC and can all output + set_safety_mode(SAFETY_HYUNDAI_ESCC, 1U); +#else // init to SILENT and can silent set_safety_mode(SAFETY_SILENT, 0U); +#endif // enable CAN TXs current_board->enable_can_transceivers(true); @@ -367,7 +431,35 @@ int main(void) { enable_interrupts(); // LED should keep on blinking all the time +#if defined(ESCC) && defined(DEBUG_CAN_LOOP) + ESCC_Msg escc; + escc.fca_cmd_act = 1; + escc.aeb_cmd_act = 1; + escc.cf_vsm_warn_fca11 = 1; + escc.cf_vsm_warn_scc12 = 1; + escc.cf_vsm_deccmdact_scc12 = 1; + escc.cf_vsm_deccmdact_fca11 = 1; + escc.cr_vsm_deccmd_scc12 = 1; + escc.cr_vsm_deccmd_fca11 = 1; + escc.obj_valid = 1; + escc.acc_objstatus = 1; + escc.acc_obj_lat_pos_1 = 1; + escc.acc_obj_lat_pos_2 = 1; + escc.acc_obj_dist_1 = 1; + escc.acc_obj_dist_2 = 1; + escc.acc_obj_rel_spd_1 = 1; + escc.acc_obj_rel_spd_2 = 1; + int i = 0; +#endif + while (true) { + +#if defined(ESCC) && defined(DEBUG_CAN_LOOP) + send_escc_msg(&escc, i++); + if(i > 3) + i = 0; +#endif + if (power_save_status == POWER_SAVE_STATUS_DISABLED) { #ifdef DEBUG_FAULTS if (fault_status == FAULT_STATUS_NONE) { diff --git a/board/safety.h b/board/safety.h index 5470e7b364..c905952ba0 100644 --- a/board/safety.h +++ b/board/safety.h @@ -23,6 +23,10 @@ #include "safety/safety_elm327.h" #include "safety/safety_body.h" +#ifdef ESCC +#include "safety/safety_hyundai_escc.h" +#endif + // CAN-FD only safety modes #ifdef CANFD #include "safety/safety_hyundai_canfd.h" @@ -56,6 +60,10 @@ #define SAFETY_BODY 27U #define SAFETY_HYUNDAI_CANFD 28U +#ifdef ESCC +#define SAFETY_HYUNDAI_ESCC 29U +#endif + uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len) { uint32_t ret = 0U; for (int i = 0; i < len; i++) { @@ -375,7 +383,9 @@ int set_safety_hooks(uint16_t mode, uint16_t param) { {SAFETY_GM, &gm_hooks}, {SAFETY_HONDA_BOSCH, &honda_bosch_hooks}, {SAFETY_HYUNDAI, &hyundai_hooks}, - {SAFETY_CHRYSLER, &chrysler_hooks}, +#ifdef ESCC + {SAFETY_HYUNDAI_ESCC, &hyundai_escc_hooks}, +#endif {SAFETY_CHRYSLER, &chrysler_hooks}, {SAFETY_SUBARU, &subaru_hooks}, {SAFETY_VOLKSWAGEN_MQB, &volkswagen_mqb_hooks}, {SAFETY_NISSAN, &nissan_hooks}, diff --git a/board/safety/safety_hyundai_escc.h b/board/safety/safety_hyundai_escc.h new file mode 100644 index 0000000000..e35497608e --- /dev/null +++ b/board/safety/safety_hyundai_escc.h @@ -0,0 +1,107 @@ +#pragma once + +#define DEVNULL_BUS (-1) +#define CAR_BUS 0 +#define RADAR_BUS 2 + +bool scc_block_allowed = false; +uint32_t sunnypilot_detected_last = 0; + +// Initialize bytes to send to 2AB +ESCC_Msg escc = {0}; + +static void escc_rx_hook(const CANPacket_t* to_push) { + const int bus = GET_BUS(to_push); + const int addr = GET_ADDR(to_push); + + + const int is_scc_msg = addr == 0x420 || addr == 0x421 || addr == 0x50A || addr == 0x389; + const int is_fca_msg = addr == 0x38D || addr == 0x483; +#ifdef DEBUG + print("escc_rx_hook: "); putui(bus); print(" - "); puth4(addr); print(" is_scc_msg: "); print(is_scc_msg?"yes":"no"); print(" is_fca_msg: "); print(is_fca_msg?"yes":"no"); print("\n"); +#endif + + if (bus == RADAR_BUS && (is_scc_msg || is_fca_msg)) { + switch (addr) { + // This messsage is blocked if scc_block_allowed is true, and ESCC is updated with the data and sent to sunnypilot + case 0x420: // SCC11: Forward radar points to sunnypilot + escc.obj_valid = (GET_BYTE(to_push, 2) & 0x1U); + escc.acc_objstatus = ((GET_BYTE(to_push, 2) >> 6) & 0x3U); + escc.acc_obj_lat_pos_1 = GET_BYTE(to_push, 3); + escc.acc_obj_lat_pos_2 = (GET_BYTE(to_push, 4) & 0x1U); + escc.acc_obj_dist_1 = ((GET_BYTE(to_push, 4) >> 1) & 0x7FU); + escc.acc_obj_dist_2 = (GET_BYTE(to_push, 5) & 0xFU); + escc.acc_obj_rel_spd_1 = ((GET_BYTE(to_push, 5) >> 4) & 0xFU); + escc.acc_obj_rel_spd_2 = GET_BYTE(to_push, 6); + send_escc_msg(&escc, CAR_BUS); + break; + + // This messsage is blocked if scc_block_allowed is true, and ESCC is updated with the data and sent to sunnypilot + case 0x421: // SCC12: Detect AEB, get the data and write it on the next ESCC msg to sunnypilot. + escc.aeb_cmd_act = GET_BYTE(to_push, 6) >> 6 & 1U; + escc.cf_vsm_warn_scc12 = GET_BYTE(to_push, 0) >> 4 & 0x3U; + escc.cf_vsm_deccmdact_scc12 = GET_BYTE(to_push, 0) >> 1 & 1U; + escc.cr_vsm_deccmd_scc12 = GET_BYTE(to_push, 2); + break; + + // This message is not blocked, and is sent straight to the car. + case 0x38D: // FCA11: Detect AEB, get the data and write it on the next ESCC msg to sunnypilot + escc.fca_cmd_act = GET_BYTE(to_push, 2) >> 4 & 1U; + escc.cf_vsm_warn_fca11 = GET_BYTE(to_push, 0) >> 3 & 0x3U; + escc.cf_vsm_deccmdact_fca11 = GET_BYTE(to_push, 3) >> 7 & 1U; + escc.cr_vsm_deccmd_fca11 = GET_BYTE(to_push, 1); + break; + + default: ; + } + } +} + +static bool escc_tx_hook(const CANPacket_t* to_send) { +#ifdef DEBUG + const int target_bus = GET_BUS(to_send); + const int addr = GET_ADDR(to_send); + print("escc_tx_hook: "); putui(target_bus); print(" - "); puth4(addr); print("\n"); + #else + UNUSED(to_send); + #endif + return true; +} + +static int escc_fwd_hook(const int bus_src, const int addr) { +#ifdef DEBUG + print("escc_fwd_hook: "); putui(bus_src); print(" - "); puth4(addr); print(" scc_block_allowed: "); print(scc_block_allowed?"yes":"no" ); print("\n"); +#endif + // SCC messages are SCC11 (0x420), SCC12 (0x421), SCC13 (0x50A), SCC14 (0x389) + const int is_scc_msg = addr == 0x420 || addr == 0x421 || addr == 0x50A || addr == 0x389; + + const uint32_t ts = MICROSECOND_TIMER->CNT; + + // Update the last detected timestamp if an SCC message is from CAR_BUS + if (bus_src == CAR_BUS && is_scc_msg) { + sunnypilot_detected_last = ts; + } + + // Default forwarding logic + int bus_dst = (bus_src == CAR_BUS) ? RADAR_BUS : CAR_BUS; + + // Update the scc_block_allowed status based on elapsed time + const uint32_t ts_elapsed = get_ts_elapsed(ts, sunnypilot_detected_last); + scc_block_allowed = (ts_elapsed <= 150000); + + // If we are allowed to block, and this is an scc msg coming from radar (or somehow we are sending it TO the radar) we block + if (scc_block_allowed && is_scc_msg && (bus_src == RADAR_BUS || bus_dst == RADAR_BUS)) + bus_dst = DEVNULL_BUS; + + return bus_dst; +} + +const safety_hooks hyundai_escc_hooks = { + .init = alloutput_init, + .rx = escc_rx_hook, + .tx = escc_tx_hook, + .fwd = escc_fwd_hook, + .get_counter = hyundai_get_counter, + .get_checksum = hyundai_get_checksum, + .compute_checksum = hyundai_compute_checksum, +}; diff --git a/board/safety_sunnypilot_common.h b/board/safety_sunnypilot_common.h new file mode 100644 index 0000000000..e2dc1db2ef --- /dev/null +++ b/board/safety_sunnypilot_common.h @@ -0,0 +1,64 @@ +#ifndef SAFETY_SUNNYPILOT_COMMON_H +#define SAFETY_SUNNYPILOT_COMMON_H + +void mads_acc_main_check(const bool main_on) { + if (main_on && mads_enabled) { + controls_allowed = true; + } + if (!main_on && acc_main_on_prev) { + disengageFromBrakes = false; + controls_allowed = false; + controls_allowed_long = false; + } + acc_main_on_prev = main_on; +} + +void mads_lkas_button_check(const bool lkas_pressed) { + if (lkas_pressed && !lkas_pressed_prev) { + controls_allowed = true; + } + lkas_pressed_prev = lkas_pressed; +} + +void mads_exit_controls_check(void) { + if (alternative_experience & ALT_EXP_MADS_DISABLE_DISENGAGE_LATERAL_ON_BRAKE) { + disengageFromBrakes = true; + controls_allowed_long = false; + } else { + if ((alternative_experience & ALT_EXP_ENABLE_MADS) && controls_allowed) { + disengageFromBrakes = true; + } + controls_allowed = false; + controls_allowed_long = false; + } +} + +void mads_resume_controls_check(void) { + disengageFromBrakes = false; + if (alternative_experience & ALT_EXP_ENABLE_MADS) { + controls_allowed = true; + } +} + +typedef struct { + uint8_t fca_cmd_act; + uint8_t aeb_cmd_act; + uint8_t cf_vsm_warn_fca11; + uint8_t cf_vsm_warn_scc12; + uint8_t cf_vsm_deccmdact_scc12; + uint8_t cf_vsm_deccmdact_fca11; + uint8_t cr_vsm_deccmd_scc12; + uint8_t cr_vsm_deccmd_fca11; + uint8_t obj_valid; + uint8_t acc_objstatus; + uint8_t acc_obj_lat_pos_1; + uint8_t acc_obj_lat_pos_2; + uint8_t acc_obj_dist_1; + uint8_t acc_obj_dist_2; + uint8_t acc_obj_rel_spd_1; + uint8_t acc_obj_rel_spd_2; +} ESCC_Msg; + +void send_escc_msg(const ESCC_Msg *msg, int bus_number); + +#endif diff --git a/tests/escc/enter_canloader.py b/tests/escc/enter_canloader.py new file mode 100755 index 0000000000..787799f245 --- /dev/null +++ b/tests/escc/enter_canloader.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +import time +import argparse +from panda import Panda, CanHandle, McuType + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Flash ESCC over can') + parser.add_argument('--recover', action='store_true') + parser.add_argument("fn", type=str, nargs='?', help="flash file") + args = parser.parse_args() + + p = Panda() + p.set_safety_mode(Panda.SAFETY_ALLOUTPUT) + + while 1: + if len(p.can_recv()) == 0: + break + + if args.recover: + p.can_send(0x200, b"\xce\xfa\xad\xde\x1e\x0b\xb0\x02", 0) + exit(0) + else: + p.can_send(0x200, b"\xce\xfa\xad\xde\x1e\x0b\xb0\x0a", 0) + + if args.fn: + time.sleep(0.1) + print("flashing", args.fn) + code = open(args.fn, "rb").read() + Panda.flash_static(CanHandle(p, 0), code, mcu_type=McuType.F4) + + print("can flash done")