191 lines
7.6 KiB
Python
191 lines
7.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Configuration file for LIN automated test scripts
|
|
|
|
This file contains all hardware-specific settings and tool dependencies.
|
|
Modify these values to match your test setup.
|
|
"""
|
|
|
|
# ============================================================================
|
|
# Hardware Configuration
|
|
# ============================================================================
|
|
|
|
# MUM (Melexis Universal Master) Configuration
|
|
MUM_HOST = '192.168.7.2' # Default MUM IP address on BeagleBone
|
|
MUM_LIN_DEVICE = 'lin0' # LIN interface name on MUM
|
|
MUM_POWER_DEVICE = 'power_out0' # Power control device name
|
|
|
|
# LIN Bus Configuration
|
|
LIN_BAUDRATE = 19200 # LIN bus baudrate in bps
|
|
|
|
# Valid NAD range for auto-addressing
|
|
VALID_NAD_RANGE = range(0x01, 0x11) # NADs 0x01 through 0x10
|
|
|
|
# ============================================================================
|
|
# External Tool Dependencies
|
|
# ============================================================================
|
|
|
|
# Python packages required (install with: pip3 install <package>)
|
|
REQUIRED_PACKAGES = [
|
|
'pylin', # LIN bus communication library
|
|
'pymumclient', # Melexis Universal Master client library
|
|
]
|
|
|
|
# ============================================================================
|
|
# Test Parameters
|
|
# ============================================================================
|
|
|
|
# Auto-addressing test defaults
|
|
AUTOADDRESSING_DEFAULT_ITERATIONS = 1 # Number of BSM iterations
|
|
AUTOADDRESSING_POLL_DURATION = 2.0 # Status polling duration between iterations (seconds)
|
|
AUTOADDRESSING_STATUS_POLL_INTERVAL = 0.020 # Status frame poll interval (20ms)
|
|
|
|
# LED control test defaults
|
|
LED_DEFAULT_NAD = 0x01 # Default NAD for LED control test
|
|
|
|
# Power cycle defaults
|
|
POWER_CYCLE_WAIT_TIME = 2.0 # Wait time after power down/up (seconds)
|
|
|
|
# ============================================================================
|
|
# Frame IDs (from 4SEVEN_color_lib_test.ldf)
|
|
# ============================================================================
|
|
|
|
LIN_FRAME_ID_MASTERREQ = 0x3C # Diagnostic master request frame
|
|
LIN_FRAME_ID_ALM_STATUS = 0x11 # ALM_Status (slave-to-master, 4 bytes)
|
|
LIN_FRAME_ID_ALM_REQ_A = 0x0A # ALM_Req_A (master-to-slave, 8 bytes, LED control)
|
|
LIN_FRAME_ID_CONFIG_FRAME = 0x06 # ConfigFrame (master-to-slave, 3 bytes)
|
|
LIN_FRAME_ID_VF_FRAME = 0x13 # VF_Frame (slave-to-master, 8 bytes, LED forward voltages + VLED)
|
|
LIN_FRAME_ID_PWM_WO_COMP = 0x15 # PWM_wo_Comp (slave-to-master, 8 bytes, PWM values + VS)
|
|
|
|
# ============================================================================
|
|
# Frame Definitions (from 4SEVEN_color_lib_test.ldf)
|
|
# ============================================================================
|
|
# Each entry mirrors the LDF Frames section. The signal tuple is:
|
|
# 'SignalName': (start_bit, width_in_bits)
|
|
# where start_bit comes from the LDF Frames block and width comes from
|
|
# the LDF Signals section. To update after an LDF change, copy the new
|
|
# Frames entry here and adjust widths from the Signals section.
|
|
#
|
|
# NAD selection for ALM_Req_A:
|
|
# node responds if AmbLightLIDFrom <= ALMNadNo <= AmbLightLIDTo
|
|
# single node -> set both to the target NAD
|
|
# broadcast -> AmbLightLIDFrom=0x01, AmbLightLIDTo=0xFF
|
|
|
|
# ALM_Req_A: 0x0A, Master_Node, 8
|
|
ALM_REQ_A_FRAME = {
|
|
'frame_id': LIN_FRAME_ID_ALM_REQ_A,
|
|
'length': 8,
|
|
'signals': {
|
|
'AmbLightColourRed': (0, 8), # AmbLightColourRed, 0;
|
|
'AmbLightColourGreen': (8, 8), # AmbLightColourGreen, 8;
|
|
'AmbLightColourBlue': (16, 8), # AmbLightColourBlue, 16;
|
|
'AmbLightIntensity': (24, 8), # AmbLightIntensity, 24;
|
|
'AmbLightUpdate': (32, 2), # AmbLightUpdate, 32;
|
|
'AmbLightMode': (34, 6), # AmbLightMode, 34;
|
|
'AmbLightDuration': (40, 8), # AmbLightDuration, 40;
|
|
'AmbLightLIDFrom': (48, 8), # AmbLightLIDFrom, 48;
|
|
'AmbLightLIDTo': (56, 8), # AmbLightLIDTo, 56;
|
|
},
|
|
}
|
|
|
|
# ALM_Status: 0x11, ALM_Node, 4
|
|
ALM_STATUS_FRAME = {
|
|
'frame_id': LIN_FRAME_ID_ALM_STATUS,
|
|
'length': 4,
|
|
'signals': {
|
|
'ALMNadNo': (0, 8), # ALMNadNo, 0;
|
|
'ALMVoltageStatus': (8, 4), # ALMVoltageStatus, 8;
|
|
'ALMThermalStatus': (12, 4), # ALMThermalStatus, 12;
|
|
'ALMNVMStatus': (16, 4), # ALMNVMStatus, 16;
|
|
'ALMLEDState': (20, 2), # ALMLEDState, 20;
|
|
'SigCommErr': (24, 1), # SigCommErr, 24;
|
|
},
|
|
}
|
|
|
|
# ConfigFrame: 6, Master_Node, 3
|
|
CONFIG_FRAME = {
|
|
'frame_id': LIN_FRAME_ID_CONFIG_FRAME,
|
|
'length': 3,
|
|
'signals': {
|
|
'ConfigFrame_Calibration': (0, 1), # ConfigFrame_Calibration, 0;
|
|
'ConfigFrame_EnableDerating': (1, 1), # ConfigFrame_EnableDerating, 1;
|
|
'ConfigFrame_EnableCompensation': (2, 1), # ConfigFrame_EnableCompensation, 2;
|
|
'ConfigFrame_MaxLM': (3, 16), # ConfigFrame_MaxLM, 3;
|
|
},
|
|
}
|
|
|
|
# VF_Frame: 19 (0x13), ALM_Node, 8
|
|
VF_FRAME = {
|
|
'frame_id': LIN_FRAME_ID_VF_FRAME,
|
|
'length': 8,
|
|
'signals': {
|
|
'VF_Frame_Red_VF': (0, 16), # VF_Frame_Red_VF, 0;
|
|
'VF_Frame_Green_VF': (16, 16), # VF_Frame_Green_VF, 16;
|
|
'VF_Frame_Blue1_VF': (32, 16), # VF_Frame_Blue1_VF, 32;
|
|
'VF_Frame_VLED': (48, 16), # VF_Frame_VLED, 48;
|
|
},
|
|
}
|
|
|
|
# PWM_wo_Comp: 21 (0x15), ALM_Node, 8
|
|
PWM_WO_COMP_FRAME = {
|
|
'frame_id': LIN_FRAME_ID_PWM_WO_COMP,
|
|
'length': 8,
|
|
'signals': {
|
|
'PWM_wo_Comp_Red': (0, 16), # PWM_wo_Comp_Red, 0;
|
|
'PWM_wo_Comp_Green': (16, 16), # PWM_wo_Comp_Green, 16;
|
|
'PWM_wo_Comp_Blue': (32, 16), # PWM_wo_Comp_Blue, 32;
|
|
'VF_Frame_VS': (48, 16), # VF_Frame_VS, 48;
|
|
},
|
|
}
|
|
|
|
|
|
def pack_frame(frame_def, **signals):
|
|
"""Pack signal values into a byte list using a frame definition.
|
|
|
|
Unlisted signals default to 0. Bit ordering follows the LDF/LIN
|
|
convention: bit 0 of the signal sits at start_bit in the frame,
|
|
packed little-endian within each byte.
|
|
"""
|
|
data = bytearray(frame_def['length'])
|
|
for name, value in signals.items():
|
|
start_bit, width = frame_def['signals'][name]
|
|
value = int(value) & ((1 << width) - 1)
|
|
for i in range(width):
|
|
bit_pos = start_bit + i
|
|
if value & (1 << i):
|
|
data[bit_pos // 8] |= 1 << (bit_pos % 8)
|
|
return list(data)
|
|
|
|
|
|
def unpack_frame(frame_def, data):
|
|
"""Unpack a received byte sequence into a dict of signal values."""
|
|
result = {}
|
|
for name, (start_bit, width) in frame_def['signals'].items():
|
|
value = 0
|
|
for i in range(width):
|
|
bit_pos = start_bit + i
|
|
if data[bit_pos // 8] & (1 << (bit_pos % 8)):
|
|
value |= 1 << i
|
|
result[name] = value
|
|
return result
|
|
|
|
# ============================================================================
|
|
# BSM-SNPD Protocol Constants
|
|
# ============================================================================
|
|
|
|
BSM_NAD_BROADCAST = 0x7F # Broadcast NAD for BSM frames
|
|
BSM_PCI = 0x06 # Protocol Control Information (6 data bytes)
|
|
BSM_SID = 0xB5 # Service ID for BSM-SNPD
|
|
BSM_SUPPLIER_ID_LSB = 0xFF # Supplier ID LSB (broadcast)
|
|
BSM_SUPPLIER_ID_MSB = 0x7F # Supplier ID MSB (broadcast)
|
|
|
|
# BSM Subfunctions
|
|
BSM_SUBF_INIT = 0x01 # Initialize auto-addressing
|
|
BSM_SUBF_ASSIGN = 0x02 # Assign NAD
|
|
BSM_SUBF_STORE = 0x03 # Store to NVM
|
|
BSM_SUBF_FINALIZE = 0x04 # Finalize auto-addressing
|
|
|
|
# Timing parameters (matching babylin behavior)
|
|
BSM_INIT_DELAY = 0.050 # Delay after INIT subfunction (50ms)
|
|
BSM_FRAME_DELAY = 0.020 # Delay between frames (20ms)
|