#include #include #include #include #include #include #include #include "common.h" #define WARN printf namespace { uint64_t set_value(uint64_t ret, Signal sig, int64_t ival){ uint64_t mask = ((1ULL << sig.b2)-1) << sig.bo; uint64_t dat = (ival & ((1ULL << sig.b2)-1)) << sig.bo; ret &= ~mask; ret |= dat; return ret; } class CANPacker { public: CANPacker(const std::string& dbc_name) { dbc = dbc_lookup(dbc_name); assert(dbc); for (int i=0; inum_msgs; i++) { const Msg* msg = &dbc->msgs[i]; message_lookup[msg->address] = *msg; for (int j=0; jnum_sigs; j++) { const Signal* sig = &msg->sigs[j]; signal_lookup[std::make_pair(msg->address, std::string(sig->name))] = *sig; } } } uint64_t pack(uint32_t address, const std::vector &signals, int counter) { uint64_t ret = 0; for (const auto& sigval : signals) { std::string name = std::string(sigval.name); double value = sigval.value; auto sig_it = signal_lookup.find(std::make_pair(address, name)); if (sig_it == signal_lookup.end()) { WARN("undefined signal %s - %d\n", name.c_str(), address); continue; } auto sig = sig_it->second; int64_t ival = (int64_t)(round((value - sig.offset) / sig.factor)); if (ival < 0) { ival = (1ULL << sig.b2) + ival; } ret = set_value(ret, sig, ival); } if (counter >= 0){ auto sig_it = signal_lookup.find(std::make_pair(address, "COUNTER")); if (sig_it == signal_lookup.end()) { WARN("COUNTER not defined\n"); return ret; } auto sig = sig_it->second; if (sig.type != SignalType::HONDA_COUNTER){ WARN("COUNTER signal type not valid\n"); } ret = set_value(ret, sig, counter); } auto sig_it = signal_lookup.find(std::make_pair(address, "CHECKSUM")); if (sig_it != signal_lookup.end()) { auto sig = sig_it->second; if (sig.type == SignalType::HONDA_CHECKSUM){ unsigned int chksm = honda_checksum(address, ret, message_lookup[address].size); ret = set_value(ret, sig, chksm); } else if (sig.type == SignalType::TOYOTA_CHECKSUM){ unsigned int chksm = toyota_checksum(address, ret, message_lookup[address].size); ret = set_value(ret, sig, chksm); } else { WARN("CHECKSUM signal type not valid\n"); } } return ret; } private: const DBC *dbc = NULL; std::map, Signal> signal_lookup; std::map message_lookup; }; } extern "C" { void* canpack_init(const char* dbc_name) { CANPacker *ret = new CANPacker(std::string(dbc_name)); return (void*)ret; } uint64_t canpack_pack(void* inst, uint32_t address, size_t num_vals, const SignalPackValue *vals, int counter, bool checksum) { CANPacker *cp = (CANPacker*)inst; return cp->pack(address, std::vector(vals, vals+num_vals), counter); } }