def process(in_fn, out_fn): dbc_name = os.path.split(out_fn)[-1].replace('.cc', '') # print("processing %s: %s -> %s" % (dbc_name, in_fn, out_fn)) template_fn = os.path.join(os.path.dirname(__file__), "dbc_template.cc") with open(template_fn, "r") as template_f: template = jinja2.Template(template_f.read(), trim_blocks=True, lstrip_blocks=True) can_dbc = dbc(in_fn) # process counter and checksums first msgs = [(address, msg_name, msg_size, sorted(msg_sigs, key=lambda s: s.name not in ("COUNTER", "CHECKSUM"))) for address, ((msg_name, msg_size), msg_sigs) in sorted(can_dbc.msgs.items()) if msg_sigs] def_vals = {a: sorted(set(b)) for a, b in can_dbc.def_vals.items()} # remove duplicates def_vals = sorted(def_vals.items()) if can_dbc.name.startswith(("honda_", "acura_")): checksum_type = "honda" checksum_size = 4 counter_size = 2 checksum_start_bit = 3 counter_start_bit = 5 little_endian = False elif can_dbc.name.startswith(("toyota_", "lexus_")): checksum_type = "toyota" checksum_size = 8 counter_size = None checksum_start_bit = 7 counter_start_bit = None little_endian = False elif can_dbc.name.startswith( ("vw_", "volkswagen_", "audi_", "seat_", "skoda_")): checksum_type = "volkswagen" checksum_size = 8 counter_size = 4 checksum_start_bit = 0 counter_start_bit = 0 little_endian = True elif can_dbc.name.startswith(("subaru_global_")): checksum_type = "subaru" checksum_size = 8 counter_size = None checksum_start_bit = 0 counter_start_bit = None little_endian = True elif can_dbc.name.startswith(("chrysler_")): checksum_type = "chrysler" checksum_size = 8 counter_size = None checksum_start_bit = 7 counter_start_bit = None little_endian = False else: checksum_type = None checksum_size = None counter_size = None checksum_start_bit = None counter_start_bit = None little_endian = None # sanity checks on expected COUNTER and CHECKSUM rules, as packer and parser auto-compute those signals for address, msg_name, _, sigs in msgs: dbc_msg_name = dbc_name + " " + msg_name for sig in sigs: if checksum_type is not None: # checksum rules if sig.name == "CHECKSUM": if sig.size != checksum_size: sys.exit("%s: CHECKSUM is not %d bits long" % (dbc_msg_name, checksum_size)) if sig.start_bit % 8 != checksum_start_bit: sys.exit("%s: CHECKSUM starts at wrong bit" % dbc_msg_name) if little_endian != sig.is_little_endian: sys.exit("%s: CHECKSUM has wrong endianness" % dbc_msg_name) # counter rules if sig.name == "COUNTER": if counter_size is not None and sig.size != counter_size: sys.exit("%s: COUNTER is not %d bits long" % (dbc_msg_name, counter_size)) if counter_start_bit is not None and sig.start_bit % 8 != counter_start_bit: print(counter_start_bit, sig.start_bit) sys.exit("%s: COUNTER starts at wrong bit" % dbc_msg_name) if little_endian != sig.is_little_endian: sys.exit("%s: COUNTER has wrong endianness" % dbc_msg_name) # pedal rules if address in [0x200, 0x201]: if sig.name == "COUNTER_PEDAL" and sig.size != 4: sys.exit("%s: PEDAL COUNTER is not 4 bits long" % dbc_msg_name) if sig.name == "CHECKSUM_PEDAL" and sig.size != 8: sys.exit("%s: PEDAL CHECKSUM is not 8 bits long" % dbc_msg_name) # Fail on duplicate message names c = Counter([msg_name for address, msg_name, msg_size, sigs in msgs]) for name, count in c.items(): if count > 1: sys.exit("%s: Duplicate message name in DBC file %s" % (dbc_name, name)) parser_code = template.render(dbc=can_dbc, checksum_type=checksum_type, msgs=msgs, def_vals=def_vals, len=len) with open(out_fn, "w") as out_f: out_f.write(parser_code)
from opendbc import DBC_PATH from cereal import car, log from common.realtime import Ratekeeper from selfdrive.config import Conversions as CV import cereal.messaging as messaging from selfdrive.car import crc8_pedal from selfdrive.car.honda.values import CAR from selfdrive.car.honda.carstate import get_can_signals from selfdrive.boardd.boardd import can_list_to_can_capnp from opendbc.can.parser import CANParser from selfdrive.car.honda.interface import CarInterface from opendbc.can.dbc import dbc honda = dbc( os.path.join(DBC_PATH, "honda_civic_touring_2016_can_generated.dbc")) # Trick: set 0x201 (interceptor) in fingerprints for gas is controlled like if there was an interceptor CP = CarInterface.get_params(CAR.CIVIC, {0: {0x201: 6}, 1: {}, 2: {}, 3: {}}) # Honda checksum def can_cksum(mm): s = 0 for c in mm: s += (c >> 4) s += c & 0xF s = 8 - s s %= 0x10 return s