DBC_Converter/DBC_Converter_TX.py

192 lines
8.2 KiB
Python

import sys
from DBC_Converter_Data_Parsing import load_dbc_file
#============================== Generate TX Globals ==============================#
def generate_tx_globals(signals, output_file, header_file):
if not signals:
print("[WARNING] No signals to generate TX globals for.")
return
with open(output_file, 'w') as f:
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_TX_GLOBALS_H\n")
f.write("#define GENERATED_TX_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_TX_GLOBALS_H\n")
print(f"[INFO] TX globals written to {output_file} and {header_file}")
#============================== Generate TX Functions ==============================#
def generate_tx_functions(signals, output_file):
if not signals:
print("[WARNING] No signals to generate TX 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 Output_Data_Set_{message_name}_CH0_{hex_id}(void)"
f.write(f"{function_name}\n{{\n")
for signal in message_info["Signals"]:
factor_str = f"/ {signal['Factor']}" if signal["Factor"] != 1.0 else ""
offset_str = f"- {signal['Offset']}" if signal["Offset"] != 0.0 else ""
mask = f"_{signal['Length']}bit"
f.write(
f" VCU.TX.CH0_{message_name}_{hex_id}.{signal['Signal name']} = "
f"(int)((GV_{signal['Signal name']} {offset_str}) {factor_str}) & {mask};\n"
)
f.write("}\n\n")
print(f"[INFO] TX functions written to {output_file}")
#============================== Generate TX Initialization ==============================#
def generate_tx_initialization(signals, output_file):
if not signals:
print("[WARNING] No TX signals found for initialization generation.")
return
with open(output_file, 'w') as f:
f.write("void Initialize_TX_Signals(void)\n{\n")
for message_name, message_info in signals.items():
hex_id = message_info["ID"]
f.write(f" // {message_name} ({hex_id})\n")
for signal in message_info["Signals"]:
f.write(f" VCU.TX.CH0_{message_name}_{hex_id}.{signal['Signal name']} = 0;\n")
f.write("\n")
f.write("}\n")
print(f"[INFO] TX initialization function written to {output_file}")
#============================== Generate TX Enum ==============================#
def generate_tx_enum(signals, output_file, cycle):
if not signals:
print("[WARNING] No TX messages found for enum generation.")
return
with open(output_file, 'w') as f:
f.write("typedef enum {\n")
for idx, message_name in enumerate(signals.keys()):
enum_name = f"VCU_CH0_TX_{message_name}_{cycle}"
f.write(f" {enum_name} = {idx},\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}")
#============================== Generate TX C File ==============================#
def generate_vcu_can_transmit_single_c_file(signals, output_file):
if not signals:
print("[ERROR] No signals to generate VCU CAN transmit functions for.")
return
# Initialize the header of the C file
c_file_content = """
#include "can.h"
"""
# Iterate through all messages in the signals
for message_name, message_info in signals.items():
# 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
# Add the function definition for the message
c_file_content += f"""
void Transmit_{message_name}_CH0_{message_info['ID']}(void)
{{
"""
# Iterate through signals and generate bit-packing logic
buffer_assignments = [""] * message_info["DLC"]
for signal in message_info["Signals"]:
start_byte = signal["msb"] // 8
start_bit = signal["msb"] % 8
signal_length = signal["Length"]
signal_name = f"VCU.TX.CH0_{message_name}_{message_info['ID']}.{signal['Signal name']}"
# Handle 8-bit chunks
while signal_length > 0:
bits_in_byte = min(8 - start_bit, signal_length)
shift_amount = (signal["Length"] - signal_length)
if signal["Byte order"] == 0: # Motorola (Big Endian)
if bits_in_byte == 8:
shift_expr = f"({signal_name} >> shift{shift_amount})"
else:
shift_expr = f"({signal_name} << shift{start_bit})" if start_bit > 0 else f"({signal_name} >> shift{shift_amount})"
else: # Intel (Little Endian)
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}"
else:
buffer_assignments[buffer_index] = f"{shift_expr}"
# Update pointers
signal_length -= bits_in_byte
start_byte += 1
start_bit = 0
# Write buffer assignments to the function
for i, assignment in enumerate(buffer_assignments):
if assignment:
c_file_content += f" CAN_ch[0].tx.buf[{i}] = ({assignment}) & _8bit;\n"
# Add the send function call
c_file_content += f"""
can_send_config(CAN_INST_0, g_messageObjectConf_VCU_0ch_TX[VCU_CH0_TX_{message_name}_10ms]);
}}
"""
# 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 C file with all VCU messages: {output_file}")
#============================== Main ==============================#
if __name__ == "__main__":
dbc_file_path = sys.argv[1]
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"
output_c_file = f"{output_dir}/Transmit_All_VCU_Messages.c" # Replace with your desired output file name
cycle_time = "10ms"
signals = load_dbc_file(dbc_file_path)
if signals is None:
print(f"[ERROR] Failed to load DBC file: {dbc_file_path}")
sys.exit(1)
generate_tx_globals(signals, output_globals_file, output_globals_header)
generate_tx_functions(signals, output_tx_functions_file)
generate_tx_initialization(signals, output_tx_initialization)
generate_tx_enum(signals, output_enum_file, cycle_time)
generate_vcu_can_transmit_single_c_file(signals, output_c_file)