Esempio n. 1
0
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)
Esempio n. 2
0
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