mirror of
https://github.com/3minbe/DBC_Converter.git
synced 2026-05-17 01:23:58 +09:00
207 lines
9.4 KiB
Python
207 lines
9.4 KiB
Python
import sys
|
|
from DBC_Converter_Data_Parsing import load_dbc_file
|
|
|
|
#============================== Generate Globals ==============================#
|
|
def generate_globals(signals, C_file, header_file):
|
|
if not signals:
|
|
print("[WARNING] No signals to generate globals for.")
|
|
return
|
|
|
|
with open(C_file, 'w') as f:
|
|
f.write("#include <generated_globals.h>\n")
|
|
|
|
for message_name, message_info in signals.items():
|
|
for signal in message_info["Signals"]:
|
|
if signal["Length"] > 32:
|
|
f.write(f"float GV_{signal['Signal name']} = 0.0f;\n")
|
|
else:
|
|
f.write(f"uint32_t GV_{signal['Signal name']} = 0;\n")
|
|
|
|
with open(header_file, 'w') as f:
|
|
f.write("#ifndef GENERATED_GLOBALS_H\n")
|
|
f.write("#define GENERATED_GLOBALS_H\n\n")
|
|
f.write("#include <stdint.h>\n\n")
|
|
for message_name, message_info in signals.items():
|
|
for signal in message_info["Signals"]:
|
|
if signal["Length"] > 32:
|
|
f.write(f"extern float GV_{signal['Signal name']};\n")
|
|
else:
|
|
f.write(f"extern uint32_t GV_{signal['Signal name']};\n")
|
|
f.write("\n#endif // GENERATED_GLOBALS_H\n")
|
|
print(f"[INFO] Globals and extern declarations written to {C_file} and {header_file}")
|
|
|
|
#============================== Generate VCU RX Function ==============================#
|
|
def generate_vcu_rx_function_with_factors(signals, output_file):
|
|
if not signals:
|
|
print("[ERROR] No signals to generate VCU RX functions for.")
|
|
return
|
|
|
|
# Initialize the header of the C file
|
|
c_file_content = """
|
|
#include "can.h"
|
|
|
|
// Declare Factors and Offsets for signals
|
|
"""
|
|
|
|
# Collect unique Factors and Offsets
|
|
factors_offsets = {}
|
|
for message_name, message_info in signals.items():
|
|
for signal in message_info["Signals"]:
|
|
factor_name = f"Factor_{str(signal['Factor']).replace('.', '_')}"
|
|
offset_name = f"Offset_m_{abs(signal['Offset']):.0f}"
|
|
if signal['Factor'] != 1:
|
|
factors_offsets[factor_name] = signal['Factor']
|
|
if signal['Offset'] != 0:
|
|
factors_offsets[offset_name] = signal['Offset']
|
|
|
|
# Add Factor and Offset variable declarations
|
|
for name, value in factors_offsets.items():
|
|
c_file_content += f"const float {name} = {value};\n"
|
|
|
|
# Add a newline for separation
|
|
c_file_content += "\n"
|
|
|
|
# Iterate through all messages in the signals
|
|
for message_name, message_info in signals.items():
|
|
# Define the temporary struct
|
|
temp_struct_name = f"{message_name}_temp"
|
|
|
|
# Check if any signal in the message has RX ECU name as VCU
|
|
has_vcu_signal = any(signal["RX ECU name"] == "VCU" for signal in message_info["Signals"])
|
|
if not has_vcu_signal:
|
|
continue # Skip this message if no signal has RX ECU name as VCU
|
|
|
|
c_file_content += f"""
|
|
void Receive_{message_name}_{message_info['ID']}(void)
|
|
{{
|
|
struct {{
|
|
"""
|
|
|
|
# Add temporary variables to the struct
|
|
for signal in message_info["Signals"]:
|
|
if signal["RX ECU name"] != "VCU":
|
|
continue # RX ECU name이 VCU가 아닌 경우 건너뜁니다.
|
|
if signal["Sign"] == "-":
|
|
signal_type = "signed int"
|
|
elif signal["Sign"] == "+":
|
|
signal_type = "unsigned int"
|
|
|
|
c_file_content += f" {signal_type} {signal['Signal name']}_temp : {signal['Length']};\n"
|
|
|
|
c_file_content += f" }} {temp_struct_name};\n\n"
|
|
|
|
# Add temp assignments
|
|
for signal in message_info["Signals"]:
|
|
if signal["RX ECU name"] != "VCU":
|
|
continue # RX ECU name이 VCU가 아닌 경우 건너뜁니다.
|
|
start_byte = signal["msb"] // 8
|
|
start_bit = signal["msb"] % 8
|
|
signal_length = signal["Length"]
|
|
if signal["Byte order"] == 0: # Motorola (Big Endian)
|
|
lsb = signal["msb"] + 8*(signal_length // 8) - (signal_length % 8 - 1)
|
|
if signal_length > 8:
|
|
# Handle multi-byte signals
|
|
shift_expr = f"(CAN_ch[0].rx.buf[{start_byte}] << shift{7 - start_bit})"
|
|
multi_byte_expr = []
|
|
for i in range((signal_length + 7) // 8):
|
|
byte_shift = (7 - start_bit) + (i * 8)
|
|
if i == 0:
|
|
multi_byte_expr.append(f"(CAN_ch[0].rx.buf[{start_byte + i}] << shift{7 - start_bit})")
|
|
else:
|
|
multi_byte_expr.append(f"(CAN_ch[0].rx.buf[{start_byte + i}] >> shift{byte_shift})")
|
|
shift_expr = " | ".join(multi_byte_expr)
|
|
else :
|
|
shift_expr = f"(CAN_ch[0].rx.buf[{start_byte}] >> shift{lsb % 8})"
|
|
else: # Intel (Little Endian)
|
|
shift_expr = f"(CAN_ch[0].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})")
|
|
else:
|
|
multi_byte_expr.append(f"(CAN_ch[0].rx.buf[{start_byte + i}] << shift{byte_shift})")
|
|
shift_expr = " | ".join(multi_byte_expr)
|
|
c_file_content += f" {temp_struct_name}.{signal['Signal name']}_temp = ({shift_expr}) & _{signal_length}bit;\n"
|
|
|
|
c_file_content += "\n"
|
|
|
|
# Assign to final ECU variables
|
|
for signal in message_info["Signals"]:
|
|
if signal["RX ECU name"] != "VCU":
|
|
continue # RX ECU name이 VCU가 아닌 경우 건너뜁니다.
|
|
factor_name = f"Factor_{str(signal['Factor']).replace('.', '_')}"
|
|
offset_name = f"Offset_m_{abs(signal['Offset']):.0f}"
|
|
factor = f" * {factor_name}" if signal['Factor'] != 1 else ""
|
|
offset = f" + {offset_name}" if signal['Offset'] != 0 else ""
|
|
temp_var = f"{temp_struct_name}.{signal['Signal name']}_temp"
|
|
c_file_content += f" VCU.RX.{message_name}_{message_info['ID']}.{signal['Signal name']} = ({temp_var}{factor}){offset};\n"
|
|
|
|
c_file_content += "}\n"
|
|
|
|
# Write the generated code to a single C file
|
|
with open(output_file, "w") as c_file:
|
|
c_file.write(c_file_content)
|
|
print(f"Generated RX function C file with Factors and Offsets: {output_file}")
|
|
|
|
#============================== Generate Input Function ==============================#
|
|
def generate_input_functions(signals, output_file):
|
|
if not signals:
|
|
print("[WARNING] No signals to generate Input functions for.")
|
|
return
|
|
|
|
with open(output_file, 'w') as f:
|
|
for message_name, message_info in signals.items():
|
|
hex_id = message_info["ID"]
|
|
function_name = f"void Input_Data_Set_{message_name}_CH0_{hex_id}(void)"
|
|
f.write(f"{function_name}\n{{\n")
|
|
for signal in message_info["Signals"]:
|
|
f.write(f" GV_{signal['Signal name']} = VCU.RX.CH0_RX_{message_name}_{hex_id}.{signal['Signal name']};\n")
|
|
f.write("}\n\n")
|
|
print(f"[INFO] Input functions written to {output_file}")
|
|
|
|
#============================== Generate Initialization ==============================#
|
|
def generate_initialization(signals, output_file):
|
|
if not signals:
|
|
print("[WARNING] No signals to generate initialization for.")
|
|
return
|
|
|
|
with open(output_file, 'w') as f:
|
|
f.write("void VCU_Data_Init(void)\n{\n")
|
|
for message_name, message_info in signals.items():
|
|
hex_id = message_info["ID"]
|
|
struct_prefix = f"VCU.RX.CH0_RX_{message_name}_{hex_id}"
|
|
for signal in message_info["Signals"]:
|
|
if signal["Offset"] != 0.0:
|
|
if signal["Length"] <= 32:
|
|
f.write(f" {struct_prefix}.{signal['Signal name']} = {signal['Offset']};\n")
|
|
else:
|
|
f.write(f" {struct_prefix}.{signal['Signal name']} = {signal['Offset']}f;\n")
|
|
else:
|
|
if signal["Length"] <= 32:
|
|
f.write(f" {struct_prefix}.{signal['Signal name']} = 0;\n")
|
|
else:
|
|
f.write(f" {struct_prefix}.{signal['Signal name']} = 0.0f;\n")
|
|
f.write("\n")
|
|
f.write("}\n")
|
|
print(f"[INFO] Initialization function written to {output_file}")
|
|
|
|
#============================== Main ==============================#
|
|
if __name__ == "__main__":
|
|
dbc_file_path = sys.argv[1]
|
|
output_dir = sys.argv[2]
|
|
|
|
output_globals_C_file = f"{output_dir}/generated_globals.c"
|
|
output_globals_header_file = f"{output_dir}/generated_globals.h"
|
|
output_c_file = f"{output_dir}/generated_receive.c"
|
|
output_input_file = f"{output_dir}/generated_input.c"
|
|
output_initialization_file = f"{output_dir}/generated_init.c"
|
|
|
|
signals = load_dbc_file(dbc_file_path)
|
|
|
|
generate_globals(signals, output_globals_C_file, output_globals_header_file)
|
|
generate_vcu_rx_function_with_factors(signals, output_c_file)
|
|
generate_input_functions(signals, output_input_file)
|
|
generate_initialization(signals, output_initialization_file) |