You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.3 KiB
111 lines
3.3 KiB
# distutils: language = c++
|
|
from libc.stdint cimport uint32_t, uint64_t
|
|
from libcpp.vector cimport vector
|
|
from libcpp.map cimport map
|
|
from libcpp.string cimport string
|
|
from libcpp cimport bool
|
|
from posix.dlfcn cimport dlopen, dlsym, RTLD_LAZY
|
|
import os
|
|
import subprocess
|
|
|
|
cdef struct SignalPackValue:
|
|
const char* name
|
|
double value
|
|
|
|
ctypedef enum SignalType:
|
|
DEFAULT,
|
|
HONDA_CHECKSUM,
|
|
HONDA_COUNTER,
|
|
TOYOTA_CHECKSUM,
|
|
PEDAL_CHECKSUM,
|
|
PEDAL_COUNTER
|
|
|
|
cdef struct Signal:
|
|
const char* name
|
|
int b1, b2, bo
|
|
bool is_signed
|
|
double factor, offset
|
|
SignalType type
|
|
|
|
|
|
|
|
cdef struct Msg:
|
|
const char* name
|
|
uint32_t address
|
|
unsigned int size
|
|
size_t num_sigs
|
|
const Signal *sigs
|
|
|
|
cdef struct Val:
|
|
const char* name
|
|
uint32_t address
|
|
const char* def_val
|
|
const Signal *sigs
|
|
|
|
cdef struct DBC:
|
|
const char* name
|
|
size_t num_msgs
|
|
const Msg *msgs
|
|
const Val *vals
|
|
size_t num_vals
|
|
|
|
ctypedef void * (*canpack_init_func)(const char* dbc_name)
|
|
ctypedef uint64_t (*canpack_pack_vector_func)(void* inst, uint32_t address, const vector[SignalPackValue] &signals, int counter)
|
|
ctypedef const DBC * (*dbc_lookup_func)(const char* dbc_name)
|
|
|
|
|
|
cdef class CANPacker(object):
|
|
cdef void *packer
|
|
cdef const DBC *dbc
|
|
cdef map[string, (int, int)] name_to_address_and_size
|
|
cdef map[int, int] address_to_size
|
|
cdef canpack_init_func canpack_init
|
|
cdef canpack_pack_vector_func canpack_pack_vector
|
|
cdef dbc_lookup_func dbc_lookup
|
|
|
|
def __init__(self, dbc_name):
|
|
can_dir = os.path.dirname(os.path.abspath(__file__))
|
|
libdbc_fn = os.path.join(can_dir, "libdbc.so")
|
|
subprocess.check_call(["make"], cwd=can_dir)
|
|
cdef void *libdbc = dlopen(libdbc_fn, RTLD_LAZY)
|
|
self.canpack_init = <canpack_init_func>dlsym(libdbc, 'canpack_init')
|
|
self.canpack_pack_vector = <canpack_pack_vector_func>dlsym(libdbc, 'canpack_pack_vector')
|
|
self.dbc_lookup = <dbc_lookup_func>dlsym(libdbc, 'dbc_lookup')
|
|
self.packer = self.canpack_init(dbc_name)
|
|
self.dbc = self.dbc_lookup(dbc_name)
|
|
num_msgs = self.dbc[0].num_msgs
|
|
for i in range(num_msgs):
|
|
msg = self.dbc[0].msgs[i]
|
|
self.name_to_address_and_size[string(msg.name)] = (msg.address, msg.size)
|
|
self.address_to_size[msg.address] = msg.size
|
|
|
|
cdef uint64_t pack(self, addr, values, counter):
|
|
cdef vector[SignalPackValue] values_thing
|
|
cdef SignalPackValue spv
|
|
for name, value in values.iteritems():
|
|
spv.name = name
|
|
spv.value = value
|
|
values_thing.push_back(spv)
|
|
|
|
return self.canpack_pack_vector(self.packer, addr, values_thing, counter)
|
|
|
|
cdef inline uint64_t ReverseBytes(self, uint64_t x):
|
|
return (((x & 0xff00000000000000ull) >> 56) |
|
|
((x & 0x00ff000000000000ull) >> 40) |
|
|
((x & 0x0000ff0000000000ull) >> 24) |
|
|
((x & 0x000000ff00000000ull) >> 8) |
|
|
((x & 0x00000000ff000000ull) << 8) |
|
|
((x & 0x0000000000ff0000ull) << 24) |
|
|
((x & 0x000000000000ff00ull) << 40) |
|
|
((x & 0x00000000000000ffull) << 56))
|
|
|
|
cpdef make_can_msg(self, name_or_addr, bus, values, counter=-1):
|
|
cdef int addr, size
|
|
if type(name_or_addr) == int:
|
|
addr = name_or_addr
|
|
size = self.address_to_size[name_or_addr]
|
|
else:
|
|
addr, size = self.name_to_address_and_size[name_or_addr]
|
|
cdef uint64_t val = self.pack(addr, values, counter)
|
|
val = self.ReverseBytes(val)
|
|
return [addr, 0, (<char *>&val)[:size], bus]
|
|
|