기타 수정정
107
DBC_Converter.py
@ -12,11 +12,12 @@ class MainView(QtWidgets.QMainWindow):
|
||||
self.version = "1.0.0" # 프로그램 버전 설정
|
||||
self.default_save_path = os.path.join(os.path.expanduser("~"), "Desktop") # 바탕화면 경로 설정
|
||||
self.file_paths = [] # 파일 경로 저장 리스트
|
||||
self.channel_info = {} # 채널 정보 초기화
|
||||
self.loadSettings() # 설정 로드
|
||||
self.setupUI() # UI 설정
|
||||
self.centerWindow() # 창을 화면 중앙에 위치
|
||||
self.sortTreeView(0, True) # 기본 파일명 오름차순 정렬
|
||||
self.channel_options = ["1", "2", "3", "4", "5", "6"] # 채널 옵션 설정
|
||||
self.channel_options = ["CH0", "CH1", "CH2", "CH3", "CH4", "CH5"] # 채널 옵션 설정
|
||||
|
||||
def loadSettings(self):
|
||||
self.settings_file = "settings.json"
|
||||
@ -24,10 +25,14 @@ class MainView(QtWidgets.QMainWindow):
|
||||
with open(self.settings_file, "r", encoding="utf-8") as file:
|
||||
self.settings = json.load(file) # 설정 파일 로드
|
||||
self.default_save_path = self.settings.get("default_save_path", self.default_save_path)
|
||||
self.file_paths = self.settings.get("file_paths", [])
|
||||
self.last_opened_dir = self.settings.get("last_opened_dir", os.path.expanduser("~"))
|
||||
# JSON 파일 내의 file_paths와 channel_info 정보 지우기
|
||||
self.settings["file_paths"] = []
|
||||
self.settings["channel_info"] = {}
|
||||
self.saveSettings()
|
||||
else:
|
||||
self.settings = {"theme": "light"} # 기본 설정
|
||||
self.default_save_path = os.path.join(os.path.expanduser("~"), "Desktop") # 바탕화면 경로 설정
|
||||
self.last_opened_dir = os.path.expanduser("~")
|
||||
|
||||
def saveSettings(self):
|
||||
@ -111,34 +116,34 @@ class MainView(QtWidgets.QMainWindow):
|
||||
|
||||
# 툴바 추가
|
||||
self.toolbar = self.addToolBar("Main Toolbar")
|
||||
|
||||
add_file_action = QtWidgets.QAction(QtGui.QIcon("img/add_file.png"), "파일 추가\n(Ctrl+O)", self)
|
||||
add_file_action.setShortcut('Ctrl+O')
|
||||
add_file_action.triggered.connect(self.FilesOpen)
|
||||
self.toolbar.addAction(add_file_action)
|
||||
|
||||
delete_file_action = QtWidgets.QAction(QtGui.QIcon("img/delete_file.png"), "선택 파일 삭제\n(Delete)", self)
|
||||
delete_file_action.setShortcut('Delete')
|
||||
delete_file_action.triggered.connect(self.deleteSelectedFiles)
|
||||
self.toolbar.addAction(delete_file_action)
|
||||
|
||||
delete_all_action = QtWidgets.QAction(QtGui.QIcon("img/delete_all.png"), "모든 파일 삭제\n(Ctrl+Shift+Delete)", self)
|
||||
delete_all_action.setShortcut('Ctrl+Shift+Delete')
|
||||
delete_all_action.triggered.connect(self.deleteAllFiles)
|
||||
self.toolbar.addAction(delete_all_action)
|
||||
|
||||
delete_description_action = QtWidgets.QAction(QtGui.QIcon("img/delete_description.png"), "알림창 내용 삭제\n(Ctrl+Shift+D)", self)
|
||||
delete_description_action.setShortcut('Ctrl+Shift+D')
|
||||
delete_description_action.triggered.connect(self.clearAlerts)
|
||||
self.toolbar.addAction(delete_description_action)
|
||||
|
||||
convert_action = QtWidgets.QAction(QtGui.QIcon("img/convert.png"), "변환\n(Ctrl+R)", self)
|
||||
convert_action.setShortcut('Ctrl+R')
|
||||
convert_action.triggered.connect(self.convertFiles)
|
||||
self.toolbar.addAction(convert_action)
|
||||
|
||||
# 상태바 추가
|
||||
self.status_bar = self.statusBar()
|
||||
self.status_bar.showMessage("준비 완료")
|
||||
self.progress_bar = QtWidgets.QProgressBar()
|
||||
self.progress_bar.setMaximumWidth(200)
|
||||
self.status_bar.addPermanentWidget(self.progress_bar)
|
||||
self.progress_bar.setVisible(False)
|
||||
|
||||
# 메인 위젯 설정
|
||||
main_widget = QtWidgets.QWidget()
|
||||
@ -158,11 +163,39 @@ class MainView(QtWidgets.QMainWindow):
|
||||
self.tree.itemDoubleClicked.connect(self.onItemDoubleClicked)
|
||||
main_layout.addWidget(self.tree)
|
||||
|
||||
# 저장 경로 설정 위젯 추가
|
||||
path_layout = QtWidgets.QHBoxLayout()
|
||||
self.path_label = QtWidgets.QLabel("저장 경로:")
|
||||
self.path_edit = QtWidgets.QLineEdit(self.default_save_path)
|
||||
self.path_edit.setReadOnly(True) # 읽기 전용으로 설정
|
||||
self.path_button = QtWidgets.QPushButton("경로 선택")
|
||||
self.path_button.clicked.connect(self.selectSavePath)
|
||||
self.open_path_button = QtWidgets.QPushButton("경로 열기")
|
||||
self.open_path_button.clicked.connect(self.openSavePath)
|
||||
path_layout.addWidget(self.path_label)
|
||||
path_layout.addWidget(self.path_edit)
|
||||
path_layout.addWidget(self.path_button)
|
||||
path_layout.addWidget(self.open_path_button)
|
||||
main_layout.addLayout(path_layout)
|
||||
|
||||
# 알림창 설정
|
||||
self.alert_text = QtWidgets.QTextEdit()
|
||||
self.alert_text.setReadOnly(True)
|
||||
self.alert_text.setAcceptRichText(True)
|
||||
main_layout.addWidget(self.alert_text)
|
||||
|
||||
def selectSavePath(self):
|
||||
selected_path = QtWidgets.QFileDialog.getExistingDirectory(self, "저장 경로 선택", self.default_save_path)
|
||||
if selected_path:
|
||||
self.default_save_path = selected_path
|
||||
self.path_edit.setText(selected_path)
|
||||
|
||||
def openSavePath(self):
|
||||
if os.path.exists(self.default_save_path):
|
||||
os.startfile(self.default_save_path)
|
||||
else:
|
||||
self.showWarning("경고", "경로가 존재하지 않습니다")
|
||||
|
||||
def openCalculator(self):
|
||||
subprocess.Popen('calc.exe')
|
||||
|
||||
@ -183,6 +216,7 @@ class MainView(QtWidgets.QMainWindow):
|
||||
)
|
||||
if file_paths:
|
||||
self.last_opened_dir = os.path.dirname(file_paths[0])
|
||||
self.file_paths = file_paths # 새로운 경로로 덮어쓰기
|
||||
existing_files = [self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())]
|
||||
duplicate_files = [os.path.split(file_path)[1] for file_path in file_paths if os.path.split(file_path)[1] in existing_files]
|
||||
new_files = [file_path for file_path in file_paths if os.path.split(file_path)[1] not in existing_files]
|
||||
@ -192,7 +226,6 @@ class MainView(QtWidgets.QMainWindow):
|
||||
self.updateAlertText(f"중복 파일 경고", duplicate_files)
|
||||
if new_files:
|
||||
self.populateTreeView(new_files)
|
||||
self.file_paths.extend(new_files) # 파일 경로 저장
|
||||
self.updateAlertText(f"파일 추가 완료", [os.path.split(file_path)[1] for file_path in new_files])
|
||||
self.saveSettings()
|
||||
|
||||
@ -205,7 +238,10 @@ class MainView(QtWidgets.QMainWindow):
|
||||
deleted_files = [item.text(0) for item in selected_items]
|
||||
for item in selected_items:
|
||||
index = self.tree.indexOfTopLevelItem(item)
|
||||
file_path = os.path.join(item.text(1), item.text(0))
|
||||
self.removeChannelInfo(file_path) # 추가된 부분
|
||||
self.tree.takeTopLevelItem(index)
|
||||
self.file_paths = [self.tree.topLevelItem(i).text(1) + '/' + self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())]
|
||||
self.updateAlertText(f"파일 삭제 완료", deleted_files)
|
||||
self.saveSettings()
|
||||
|
||||
@ -215,10 +251,21 @@ class MainView(QtWidgets.QMainWindow):
|
||||
self.updateAlertText("모든 파일 삭제 실패", ["삭제할 파일이 없습니다"])
|
||||
return
|
||||
deleted_files = [self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())]
|
||||
for i in range(self.tree.topLevelItemCount()):
|
||||
item = self.tree.topLevelItem(i)
|
||||
file_path = os.path.join(item.text(1), item.text(0))
|
||||
self.removeChannelInfo(file_path) # 추가된 부분
|
||||
self.tree.clear()
|
||||
self.file_paths = []
|
||||
self.updateAlertText(f"모든 파일 삭제 완료", deleted_files)
|
||||
self.saveSettings()
|
||||
|
||||
def removeChannelInfo(self, file_path):
|
||||
if "channel_info" in self.settings and file_path in self.settings["channel_info"]:
|
||||
del self.settings["channel_info"][file_path]
|
||||
self.saveSettings()
|
||||
print(f"[INFO] Removed channel info for {file_path}")
|
||||
|
||||
def clearAlerts(self):
|
||||
self.alert_text.clear()
|
||||
|
||||
@ -242,6 +289,9 @@ class MainView(QtWidgets.QMainWindow):
|
||||
for i in range(self.tree.topLevelItemCount()):
|
||||
item = self.tree.takeTopLevelItem(0)
|
||||
items.append(item)
|
||||
if col == 3: # 파일크기 정렬
|
||||
items.sort(key=lambda x: float(x.text(col).replace(" KB", "")), reverse=reverse)
|
||||
else:
|
||||
items.sort(key=lambda x: x.text(col), reverse=reverse)
|
||||
for item in items:
|
||||
self.tree.addTopLevelItem(item)
|
||||
@ -309,23 +359,43 @@ class MainView(QtWidgets.QMainWindow):
|
||||
fsize = format_file_size(os.path.getsize(file_path))
|
||||
item = QtWidgets.QTreeWidgetItem([file, directory, self.channel_options[0], fsize])
|
||||
self.tree.addTopLevelItem(item)
|
||||
self.updateChannelInfo(directory, file, self.channel_options[0]) # Set default channel to 0
|
||||
self.file_paths = [self.tree.topLevelItem(i).text(1) + '/' + self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())]
|
||||
self.saveSettings()
|
||||
|
||||
def updateAlertText(self, message, file_list):
|
||||
current_time = QtCore.QDateTime.currentDateTime().toString("yyyy-MM-dd HH:mm:ss")
|
||||
current_time = QtCore.QDateTime.currentDateTime().toString("yy-MM-dd-ddd HH:mm:ss")
|
||||
self.alert_text.append(f"[{current_time}] {message}")
|
||||
for file in file_list:
|
||||
self.alert_text.append(f" - {file}")
|
||||
self.alert_text.setAlignment(QtCore.Qt.AlignLeft)
|
||||
self.alert_text.setStyleSheet("QTextEdit { line-height: 2.5; } border-radius: 3px;")
|
||||
self.alert_text.append("") # 한 줄 띄우기
|
||||
|
||||
def convertFiles(self):
|
||||
for file_path in self.file_paths:
|
||||
if not self.file_paths:
|
||||
self.showWarning("경고", "변환할 파일이 없습니다")
|
||||
self.updateAlertText("변환 실패", ["변환할 파일이 없습니다"])
|
||||
return
|
||||
self.status_bar.showMessage("변환 중...")
|
||||
self.progress_bar.setVisible(True)
|
||||
self.progress_bar.setValue(0)
|
||||
total_files = len(self.file_paths)
|
||||
timestamp = datetime.now().strftime("%y-%m-%d")
|
||||
for index, file_path in enumerate(self.file_paths):
|
||||
file_name = os.path.splitext(os.path.basename(file_path))[0]
|
||||
rx_output_dir = os.path.join(self.default_save_path, "DBC 변환", timestamp, file_name, "RX")
|
||||
tx_output_dir = os.path.join(self.default_save_path, "DBC 변환", timestamp, file_name, "TX")
|
||||
os.makedirs(rx_output_dir, exist_ok=True)
|
||||
os.makedirs(tx_output_dir, exist_ok=True)
|
||||
channel_info = self.settings.get("channel_info", {}).get(file_path, "0")
|
||||
try:
|
||||
subprocess.run(["python", "DBC_to_C_RX.py", file_path], check=True)
|
||||
subprocess.run(["python", "DBC_to_C_TX.py", file_path], check=True)
|
||||
subprocess.run(["python", "DBC_to_C_RX.py", file_path, rx_output_dir, channel_info], check=True)
|
||||
subprocess.run(["python", "DBC_to_C_TX.py", file_path, tx_output_dir, channel_info], check=True)
|
||||
self.updateAlertText(f"변환 성공", [file_path])
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.updateAlertText(f"변환 실패: {e}", [file_path])
|
||||
self.progress_bar.setValue(int((index + 1) / total_files * 100))
|
||||
self.status_bar.showMessage("변환 완료")
|
||||
self.progress_bar.setVisible(False)
|
||||
|
||||
def onHeaderClicked(self, logicalIndex):
|
||||
header = self.tree.headerItem()
|
||||
@ -370,8 +440,17 @@ class MainView(QtWidgets.QMainWindow):
|
||||
|
||||
def applyChannelSelection(self, item, combo, dialog):
|
||||
item.setText(2, combo.currentText())
|
||||
self.updateChannelInfo(item.text(1), item.text(0), combo.currentText()) # 추가된 부분
|
||||
dialog.close()
|
||||
|
||||
def updateChannelInfo(self, directory, filename, channel):
|
||||
file_path = os.path.join(directory, filename)
|
||||
if "channel_info" not in self.settings:
|
||||
self.settings["channel_info"] = {}
|
||||
self.settings["channel_info"][file_path] = channel
|
||||
self.saveSettings()
|
||||
print(f"[INFO] Updated channel info for {file_path} to {channel}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
main_view = MainView()
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import re
|
||||
import sys
|
||||
import cantools
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
def parse_dbc_file(file_path):
|
||||
signals = []
|
||||
@ -93,12 +95,12 @@ def parse_dbc_file(file_path):
|
||||
return signals
|
||||
|
||||
|
||||
def generate_vcu_rx_function_with_factors(dbc_path, output_file):
|
||||
def generate_vcu_rx_function_with_factors(dbc_path, output_file, channel_info):
|
||||
# Load the DBC file
|
||||
db = cantools.database.load_file(dbc_path)
|
||||
|
||||
# Initialize the header of the C file
|
||||
c_file_content = """
|
||||
c_file_content = f"""
|
||||
#include "can.h"
|
||||
|
||||
// Declare Factors and Offsets for signals
|
||||
@ -128,9 +130,10 @@ def generate_vcu_rx_function_with_factors(dbc_path, output_file):
|
||||
# Check if "VCU" is in the receivers list
|
||||
if "VCU" in message.receivers:
|
||||
# Define the temporary struct
|
||||
temp_struct_name = f"CH0_MV1_0x{message.frame_id:X}_temp"
|
||||
channel = channel_info.get(str(message.frame_id), "CH0") # 기본 채널 설정
|
||||
temp_struct_name = f"{channel}_MV1_0x{message.frame_id:X}_temp"
|
||||
c_file_content += f"""
|
||||
void Receive_{message.name}_CH0_0x{message.frame_id:X}(void)
|
||||
void Receive_{message.name}_{channel}_0x{message.frame_id:X}(void)
|
||||
{{
|
||||
struct {{
|
||||
"""
|
||||
@ -150,16 +153,16 @@ void Receive_{message.name}_CH0_0x{message.frame_id:X}(void)
|
||||
start_byte = signal.start // 8
|
||||
start_bit = signal.start % 8
|
||||
signal_length = signal.length
|
||||
shift_expr = f"(CAN_ch[0].rx.buf[{start_byte}] >> shift{start_bit})"
|
||||
shift_expr = f"(CAN_ch[{channel}].rx.buf[{start_byte}] >> shift{start_bit})"
|
||||
if signal_length > 8:
|
||||
# Handle multi-byte signals
|
||||
multi_byte_expr = []
|
||||
for i in range((signal_length + 7) // 8):
|
||||
byte_shift = i * 8
|
||||
if i == 0:
|
||||
multi_byte_expr.append(f"(CAN_ch[0].rx.buf[{start_byte + i}] >> shift{start_bit})")
|
||||
multi_byte_expr.append(f"(CAN_ch[{channel}].rx.buf[{start_byte + i}] >> shift{start_bit})")
|
||||
else:
|
||||
multi_byte_expr.append(f"(CAN_ch[0].rx.buf[{start_byte + i}] << shift{byte_shift})")
|
||||
multi_byte_expr.append(f"(CAN_ch[{channel}].rx.buf[{start_byte + i}] << shift{byte_shift})")
|
||||
shift_expr = " | ".join(multi_byte_expr)
|
||||
c_file_content += f" {temp_struct_name}.{signal.name}_temp = ({shift_expr}) & _{signal_length}bit;\n"
|
||||
|
||||
@ -168,14 +171,14 @@ void Receive_{message.name}_CH0_0x{message.frame_id:X}(void)
|
||||
# Assign to final ECU variables
|
||||
for signal in message.signals:
|
||||
factor_name = f"Factor_{str(signal.scale).replace('.', '_')}"
|
||||
offset_name = f"Offset_m_{abs(signal.offset):.0f}"
|
||||
offset_name = f"Offset_m_{abs(signal.offset)::.0f}"
|
||||
factor = f" * {factor_name}" if signal.scale != 1 else ""
|
||||
offset = f" + {offset_name}" if signal.offset != 0 else ""
|
||||
temp_var = f"{temp_struct_name}.{signal.name}_temp"
|
||||
if signal.is_signed:
|
||||
c_file_content += f" ECU3.RX.CH0_{message.name}_0x{message.frame_id:X}.{signal.name} = ({temp_var}{factor}){offset};\n"
|
||||
c_file_content += f" VCU.RX.{channel}_{message.name}_0x{message.frame_id:X}.{signal.name} = ({temp_var}{factor}){offset};\n"
|
||||
else:
|
||||
c_file_content += f" ECU3.RX.CH0_{message.name}_0x{message.frame_id:X}.{signal.name} = {temp_var}{factor}{offset};\n"
|
||||
c_file_content += f" VCU.RX.{channel}_{message.name}_0x{message.frame_id:X}.{signal.name} = {temp_var}{factor}{offset};\n"
|
||||
|
||||
c_file_content += "}\n"
|
||||
|
||||
@ -185,7 +188,7 @@ void Receive_{message.name}_CH0_0x{message.frame_id:X}(void)
|
||||
print(f"Generated RX function C file with Factors and Offsets: {output_file}")
|
||||
|
||||
|
||||
def generate_input_functions(signals, output_file):
|
||||
def generate_input_functions(signals, output_file, channel_info):
|
||||
if not signals:
|
||||
print("[WARNING] No signals to generate Input functions for.")
|
||||
return
|
||||
@ -193,15 +196,16 @@ def generate_input_functions(signals, output_file):
|
||||
with open(output_file, 'w') as f:
|
||||
for message in signals:
|
||||
hex_id = f"0x{int(message['id']):X}"
|
||||
function_name = f"void Input_Data_Set_{message['name']}_CH0_{hex_id}(void)"
|
||||
channel = channel_info.get(str(message['id']), "CH0")
|
||||
function_name = f"void Input_Data_Set_{message['name']}_{channel}_{hex_id}(void)"
|
||||
f.write(f"{function_name}\n{{\n")
|
||||
for signal in message["signals"]:
|
||||
f.write(f" GV_{signal['name']} = ECU3.RX.CH0_RX_{message['name']}_{hex_id}.{signal['name']};\n")
|
||||
f.write(f" GV_{signal['name']} = VCU.RX.{channel}_RX_{message['name']}_{hex_id}.{signal['name']};\n")
|
||||
f.write("}\n\n")
|
||||
print(f"[INFO] Input functions written to {output_file}")
|
||||
|
||||
|
||||
def generate_structs(signals, output_file):
|
||||
def generate_structs(signals, output_file, channel_info):
|
||||
if not signals:
|
||||
print("[WARNING] No signals to generate structs for.")
|
||||
return
|
||||
@ -213,18 +217,19 @@ def generate_structs(signals, output_file):
|
||||
|
||||
for message in signals:
|
||||
hex_id = f"0x{int(message['id']):X}"
|
||||
channel = channel_info.get(str(message['id']), "CH0")
|
||||
f.write(f"typedef struct\n{{\n")
|
||||
for signal in message["signals"]:
|
||||
if signal["size"] <= 32:
|
||||
f.write(f" uint32_t {signal['name']} : {signal['size']};\n")
|
||||
else:
|
||||
f.write(f" float {signal['name']};\n")
|
||||
f.write(f"}} CH0_RX_{message['name']}_{hex_id};\n\n")
|
||||
f.write(f"}} {channel}_RX_{message['name']}_{hex_id};\n\n")
|
||||
f.write("#endif // GENERATED_STRUCTS_H\n")
|
||||
print(f"[INFO] Structs written to {output_file}")
|
||||
|
||||
|
||||
def generate_globals(signals, output_file, header_file):
|
||||
def generate_globals(signals, output_file, header_file, channel_info):
|
||||
if not signals:
|
||||
print("[WARNING] No signals to generate globals for.")
|
||||
return
|
||||
@ -233,6 +238,7 @@ def generate_globals(signals, output_file, header_file):
|
||||
f.write("#include <generated_globals.h>\n")
|
||||
|
||||
for message in signals:
|
||||
channel = channel_info.get(str(message['id']), "CH0")
|
||||
for signal in message["signals"]:
|
||||
if signal["size"] > 32:
|
||||
f.write(f"float GV_{signal['name']} = 0.0f;\n")
|
||||
@ -244,6 +250,7 @@ def generate_globals(signals, output_file, header_file):
|
||||
f.write("#define GENERATED_GLOBALS_H\n\n")
|
||||
f.write("#include <stdint.h>\n\n")
|
||||
for message in signals:
|
||||
channel = channel_info.get(str(message['id']), "CH0")
|
||||
for signal in message["signals"]:
|
||||
if signal["size"] > 32:
|
||||
f.write(f"extern float GV_{signal['name']};\n")
|
||||
@ -253,16 +260,17 @@ def generate_globals(signals, output_file, header_file):
|
||||
print(f"[INFO] Globals and extern declarations written to {output_file} and {header_file}")
|
||||
|
||||
|
||||
def generate_initialization(signals, output_file):
|
||||
def generate_initialization(signals, output_file, channel_info):
|
||||
if not signals:
|
||||
print("[WARNING] No signals to generate initialization for.")
|
||||
return
|
||||
|
||||
with open(output_file, 'w') as f:
|
||||
f.write("void ECU3_Data_Init(void)\n{\n")
|
||||
f.write("void VCU_Data_Init(void)\n{\n")
|
||||
for message in signals:
|
||||
hex_id = f"0x{int(message['id']):X}"
|
||||
struct_prefix = f"ECU3.RX.CH0_RX_{message['name']}_{hex_id}"
|
||||
channel = channel_info.get(str(message['id']), "CH0")
|
||||
struct_prefix = f"VCU.RX.{channel}_RX_{message['name']}_{hex_id}"
|
||||
for signal in message["signals"]:
|
||||
if signal["offset"] != 0.0:
|
||||
if signal["size"] <= 32:
|
||||
@ -281,17 +289,32 @@ def generate_initialization(signals, output_file):
|
||||
|
||||
if __name__ == "__main__":
|
||||
dbc_file_path = sys.argv[1]
|
||||
output_c_file = "C:/Users/MSI/Desktop/DB/generated_receive.c"
|
||||
output_input_file = "C:/Users/MSI/Desktop/DB/generated_input.c"
|
||||
output_structs_file = "C:/Users/MSI/Desktop/DB/generated_structs.h"
|
||||
output_globals_file = "C:/Users/MSI/Desktop/DB/generated_globals.c"
|
||||
output_globals_header = "C:/Users/MSI/Desktop/DB/generated_globals.h"
|
||||
output_initialization_file = "C:/Users/MSI/Desktop/DB/generated_init.c"
|
||||
output_dir = sys.argv[2]
|
||||
channel_info_path = sys.argv[3]
|
||||
|
||||
with open(channel_info_path, 'r', encoding='cp1252') as f:
|
||||
try:
|
||||
channel_info = json.load(f)
|
||||
# Convert channel info to int
|
||||
for key in channel_info:
|
||||
channel_info[key] = int(channel_info[key].replace("CH", ""))
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"[ERROR] Error decoding JSON: {e}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error reading channel info file: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
output_c_file = f"{output_dir}/generated_receive.c"
|
||||
output_input_file = f"{output_dir}/generated_input.c"
|
||||
output_structs_file = f"{output_dir}/generated_structs.h"
|
||||
output_globals_file = f"{output_dir}/generated_globals.c"
|
||||
output_globals_header = f"{output_dir}/generated_globals.h"
|
||||
output_initialization_file = f"{output_dir}/generated_init.c"
|
||||
|
||||
signals = parse_dbc_file(dbc_file_path)
|
||||
generate_vcu_rx_function_with_factors(dbc_file_path, output_c_file)
|
||||
generate_input_functions(signals, output_input_file)
|
||||
generate_structs(signals, output_structs_file)
|
||||
generate_globals(signals, output_globals_file, output_globals_header)
|
||||
generate_initialization(signals, output_initialization_file)
|
||||
|
||||
generate_vcu_rx_function_with_factors(dbc_file_path, output_c_file, channel_info)
|
||||
generate_input_functions(signals, output_input_file, channel_info)
|
||||
generate_structs(signals, output_structs_file, channel_info)
|
||||
generate_globals(signals, output_globals_file, output_globals_header, channel_info)
|
||||
generate_initialization(signals, output_initialization_file, channel_info)
|
||||
@ -1,6 +1,8 @@
|
||||
import re
|
||||
import sys
|
||||
import cantools
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
def parse_dbc_file(file_path):
|
||||
signals = []
|
||||
@ -158,7 +160,7 @@ def generate_tx_functions(signals, output_file):
|
||||
offset_str = f"- {signal['offset']}" if signal["offset"] != 0.0 else ""
|
||||
mask = f"_{signal['size']}bit"
|
||||
f.write(
|
||||
f" ECU3.TX.CH0_{message['name']}_{hex_id}.{signal['name']} = "
|
||||
f" VCU.TX.CH0_{message['name']}_{hex_id}.{signal['name']} = "
|
||||
f"(int)((GV_{signal['name']} {offset_str}) {factor_str}) & {mask};\n"
|
||||
)
|
||||
f.write("}\n\n")
|
||||
@ -175,7 +177,7 @@ def generate_tx_initialization(signals, output_file):
|
||||
hex_id = f"0x{int(message['id']):X}"
|
||||
f.write(f" // {message['name']} ({hex_id})\n")
|
||||
for signal in message["signals"]:
|
||||
f.write(f" ECU3.TX.CH0_{message['name']}_{hex_id}.{signal['name']} = 0;\n")
|
||||
f.write(f" VCU.TX.CH0_{message['name']}_{hex_id}.{signal['name']} = 0;\n")
|
||||
f.write("\n")
|
||||
f.write("}\n")
|
||||
print(f"[INFO] TX initialization function written to {output_file}")
|
||||
@ -223,10 +225,10 @@ def generate_tx_enum(tx_messages, output_file, cycle):
|
||||
with open(output_file, 'w') as f:
|
||||
f.write("typedef enum {\n")
|
||||
for idx, message in enumerate(tx_messages):
|
||||
enum_name = f"ECU3_CH0_TX_{message}_{cycle}"
|
||||
enum_name = f"VCU_CH0_TX_{message}_{cycle}"
|
||||
f.write(f" {enum_name} = {idx},\n")
|
||||
f.write(" NUMBER_OF_ECU3_CH0_TX_MESSAGE,\n")
|
||||
f.write("} ECU3_CH0_TX;\n")
|
||||
f.write(" NUMBER_OF_VCU_CH0_TX_MESSAGE,\n")
|
||||
f.write("} VCU_CH0_TX;\n")
|
||||
print(f"[INFO] TX enum written to {output_file}")
|
||||
|
||||
def generate_vcu_can_transmit_single_c_file(dbc_path, output_file):
|
||||
@ -254,7 +256,7 @@ void Transmit_{message.name}_CH0_0x{message.frame_id:X}(void)
|
||||
start_byte = signal.start // 8
|
||||
start_bit = signal.start % 8
|
||||
signal_length = signal.length
|
||||
signal_name = f"ECU3.TX.CH0_{message.name}_0x{message.frame_id:X}.{signal.name}"
|
||||
signal_name = f"VCU.TX.CH0_{message.name}_0x{message.frame_id:X}.{signal.name}"
|
||||
|
||||
# Handle 8-bit chunks
|
||||
while signal_length > 0:
|
||||
@ -263,6 +265,11 @@ void Transmit_{message.name}_CH0_0x{message.frame_id:X}(void)
|
||||
shift_expr = f"({signal_name} >> shift{shift_amount}) << shift{start_bit}" if start_bit > 0 else f"({signal_name} >> shift{shift_amount})"
|
||||
buffer_index = start_byte
|
||||
|
||||
# Ensure buffer_index is within the range of buffer_assignments
|
||||
if buffer_index >= len(buffer_assignments):
|
||||
print(f"[ERROR] Buffer index {buffer_index} out of range for message {message.name}")
|
||||
break
|
||||
|
||||
# Add to the buffer assignments
|
||||
if buffer_assignments[buffer_index]:
|
||||
buffer_assignments[buffer_index] += f"\n | {shift_expr}"
|
||||
@ -281,7 +288,7 @@ void Transmit_{message.name}_CH0_0x{message.frame_id:X}(void)
|
||||
|
||||
# Add the send function call
|
||||
c_file_content += f"""
|
||||
can_send_config(CAN_INST_0, g_messageObjectConf_ECU3_0ch_TX[ECU3_CH0_TX_{message.name}_10ms]);
|
||||
can_send_config(CAN_INST_0, g_messageObjectConf_VCU_0ch_TX[VCU_CH0_TX_{message.name}_10ms]);
|
||||
}}
|
||||
"""
|
||||
|
||||
@ -293,14 +300,16 @@ void Transmit_{message.name}_CH0_0x{message.frame_id:X}(void)
|
||||
|
||||
if __name__ == "__main__":
|
||||
dbc_file_path = sys.argv[1]
|
||||
output_structs_file = "C:/Users/MSI/Desktop/DB/generated_tx_structs.h"
|
||||
output_globals_file = "C:/Users/MSI/Desktop/DB/generated_tx_globals.c"
|
||||
output_globals_header = "C:/Users/MSI/Desktop/DB/generated_tx_globals.h"
|
||||
output_tx_functions_file = "C:/Users/MSI/Desktop/DB/generated_tx_functions.c"
|
||||
output_tx_initialization = "C:/Users/MSI/Desktop/DB/generated_tx_initialization.c"
|
||||
output_enum_file = "C:/Users/MSI/Desktop/DB/generated_tx_enum.h"
|
||||
output_dir = sys.argv[2]
|
||||
|
||||
output_structs_file = f"{output_dir}/generated_tx_structs.h"
|
||||
output_globals_file = f"{output_dir}/generated_tx_globals.c"
|
||||
output_globals_header = f"{output_dir}/generated_tx_globals.h"
|
||||
output_tx_functions_file = f"{output_dir}/generated_tx_functions.c"
|
||||
output_tx_initialization = f"{output_dir}/generated_tx_initialization.c"
|
||||
output_enum_file = f"{output_dir}/generated_tx_enum.h"
|
||||
cycle_time = "10ms"
|
||||
output_c_file = "C:/Users/MSI/Desktop/DB/Transmit_All_VCU_Messages.c" # Replace with your desired output file name
|
||||
output_c_file = f"{output_dir}/Transmit_All_VCU_Messages.c" # Replace with your desired output file name
|
||||
|
||||
generate_vcu_can_transmit_single_c_file(dbc_file_path, output_c_file)
|
||||
|
||||
|
||||
BIN
img/add_file.png
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 16 KiB |
BIN
img/add_folder.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 16 KiB |
@ -1,14 +1,11 @@
|
||||
{
|
||||
"theme": "light",
|
||||
"default_save_path": "C:\\Users\\blueb\\Desktop",
|
||||
"default_save_path": "C:/Users/MSI/Desktop",
|
||||
"file_paths": [
|
||||
"C:/Users/blueb/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC/240906_VCU_SCU_RWS.dbc",
|
||||
"C:/Users/blueb/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC/CAN_2023WRS_RG3EV_231123_VCU_EMB.dbc",
|
||||
"C:/Users/blueb/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC/240906_VCU_SCU_RWS.dbc",
|
||||
"C:/Users/blueb/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC/241007_primary_HyperSafe4.dbc",
|
||||
"C:/Users/blueb/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC/CAN_2023WRS_RG3EV_240626_VCU_BCU.dbc",
|
||||
"C:/Users/blueb/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC/CANFD_SAFETY_v7.dbc",
|
||||
"C:/Users/blueb/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC/IMU_SBW_20240826.dbc"
|
||||
"C:/Users/MSI/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC/240321_PHM.dbc"
|
||||
],
|
||||
"last_opened_dir": "C:/Users/blueb/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC"
|
||||
"last_opened_dir": "C:/Users/MSI/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC",
|
||||
"channel_info": {
|
||||
"C:/Users/MSI/SynologyDrive/3min_be/한자연/!사업/초안전/#Debug/DBC\\240321_PHM.dbc": "CH1"
|
||||
}
|
||||
}
|
||||