diff --git a/can/common.cc b/can/common.cc index d0ace8c..408975e 100644 --- a/can/common.cc +++ b/can/common.cc @@ -69,6 +69,7 @@ unsigned int chrysler_checksum(unsigned int address, uint64_t d, int l) { // Static lookup table for fast computation of CRC8 poly 0x2F, aka 8H2F/AUTOSAR uint8_t crc8_lut_8h2f[256]; +uint8_t crc8_lut_d5[256]; void gen_crc_lookup_table(uint8_t poly, uint8_t crc_lut[]) { uint8_t crc; @@ -90,6 +91,7 @@ void init_crc_lookup_tables() { // At init time, set up static lookup tables for fast CRC computation. gen_crc_lookup_table(0x2F, crc8_lut_8h2f); // CRC-8 8H2F/AUTOSAR for Volkswagen + gen_crc_lookup_table(0xD5, crc8_lut_d5); // CRC-8 for pedal } unsigned int volkswagen_crc(unsigned int address, uint64_t d, int l) { @@ -190,6 +192,16 @@ unsigned int pedal_checksum(uint64_t d, int l) { return crc; } +unsigned int ocelot_checksum(uint64_t d, int l) { + uint8_t crc = 0xFF; // Standard init value for CRC8 + + // CRC the payload, skipping over the first byte where the CRC lives. + for (int i = 1; i < l; i++) { + crc ^= (d >> (i*8)) & 0xFF; + crc = crc8_lut_d5[crc]; + } + return crc; +} uint64_t read_u64_be(const uint8_t* v) { return (((uint64_t)v[0] << 56) diff --git a/can/common.h b/can/common.h index dd91a6c..219dd6c 100644 --- a/can/common.h +++ b/can/common.h @@ -18,6 +18,7 @@ unsigned int chrysler_checksum(unsigned int address, uint64_t d, int l); void init_crc_lookup_tables(); unsigned int volkswagen_crc(unsigned int address, uint64_t d, int l); unsigned int pedal_checksum(uint64_t d, int l); +unsigned int ocelot_checksum(uint64_t d, int l); uint64_t read_u64_be(const uint8_t* v); uint64_t read_u64_le(const uint8_t* v); diff --git a/can/common_dbc.h b/can/common_dbc.h index e5c12ba..e4fbee6 100644 --- a/can/common_dbc.h +++ b/can/common_dbc.h @@ -40,6 +40,8 @@ enum SignalType { VOLKSWAGEN_COUNTER, SUBARU_CHECKSUM, CHRYSLER_CHECKSUM, + OCELOT_CHECKSUM, + OCELOT_COUNTER, }; struct Signal { diff --git a/can/dbc_template.cc b/can/dbc_template.cc index f6d4988..63cb5e8 100644 --- a/can/dbc_template.cc +++ b/can/dbc_template.cc @@ -37,6 +37,10 @@ const Signal sigs_{{address}}[] = { .type = SignalType::PEDAL_CHECKSUM, {% elif address in [512, 513] and sig.name == "COUNTER_PEDAL" %} .type = SignalType::PEDAL_COUNTER, + {% if checksum_type == "ocelot" and sig.name == "CHECKSUM" %} + .type = SignalType::OCELOT_CHECKSUM, + {% elif checksum_type == "ocelot" and sig.name == "COUNTER" %} + .type = SignalType::OCELOT_COUNTER, {% else %} .type = SignalType::DEFAULT, {% endif %} diff --git a/can/packer.cc b/can/packer.cc index ba675a5..b9b65db 100644 --- a/can/packer.cc +++ b/can/packer.cc @@ -77,7 +77,7 @@ uint64_t CANPacker::pack(uint32_t address, const std::vector &s } auto sig = sig_it->second; - if ((sig.type != SignalType::HONDA_COUNTER) && (sig.type != SignalType::VOLKSWAGEN_COUNTER)) { + if ((sig.type != SignalType::HONDA_COUNTER) && (sig.type != SignalType::VOLKSWAGEN_COUNTER) && (sig.type != SignalType::OCELOT_COUNTER)) { WARN("COUNTER signal type not valid\n"); } @@ -105,7 +105,10 @@ uint64_t CANPacker::pack(uint32_t address, const std::vector &s } else if (sig.type == SignalType::CHRYSLER_CHECKSUM) { unsigned int chksm = chrysler_checksum(address, ReverseBytes(ret), message_lookup[address].size); ret = set_value(ret, sig, chksm); - } else { + } else if (sig.type == SignalType::OCELOT_CHECKSUM) { + unsigned int chksm = chrysler_checksum(ret, message_lookup[address].size); + ret = set_value(ret, sig, chksm); + else { //WARN("CHECKSUM signal type not valid\n"); } } diff --git a/can/parser.cc b/can/parser.cc index c6d85d9..beae589 100644 --- a/can/parser.cc +++ b/can/parser.cc @@ -76,6 +76,15 @@ bool MessageState::parse(uint64_t sec, uint16_t ts_, uint8_t * dat) { if (!update_counter_generic(tmp, sig.b2)) { return false; } + } else if (sig.type == SignalType::OCELOT_CHECKSUM) { + if (ocelot_checksum(dat_be, size) != tmp) { + INFO("0x%X OCELOT CHECKSUM FAIL\n", address); + return false; + } + } else if (sig.type == SignalType::OCELOT_COUNTER) { + if (!update_counter_generic(tmp, sig.b2)) { + return false; + } } vals[i] = tmp * sig.factor + sig.offset; diff --git a/can/process_dbc.py b/can/process_dbc.py index 9025331..44a0c36 100755 --- a/can/process_dbc.py +++ b/can/process_dbc.py @@ -61,6 +61,13 @@ def process(in_fn, out_fn): checksum_start_bit = 7 counter_start_bit = None little_endian = False +elif can_dbc.name.startswith(("ocelot_")): + checksum_type = "ocelot" + checksum_size = 8 + counter_size = 4 + checksum_start_bit = 0 + counter_start_bit = 4 + little_endian = True else: checksum_type = None checksum_size = None diff --git a/ocelot_can.dbc b/ocelot_can.dbc index 6048af8..3647d36 100644 --- a/ocelot_can.dbc +++ b/ocelot_can.dbc @@ -59,21 +59,21 @@ BO_ 512 GAS_COMMAND: 8 EON SG_ GAS_COMMAND : 7|16@0+ (0.159375,-75.555) [0|1] "" PED SG_ GAS_COMMAND2 : 23|16@0+ (0.159375,-151.111) [0|1] "" PED SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" PED - SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" PED - SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" PED + SG_ COUNTER : 32|4@1+ (1,0) [0|15] "" PED + SG_ CHECKSUM : 40|8@1+ (1,0) [0|255] "" PED BO_ 513 GAS_SENSOR: 8 PED SG_ PED_GAS : 7|16@0+ (0.159375,-75.555) [0|1] "" EON SG_ PED_GAS2 : 23|16@0+ (0.159375,-151.111) [0|1] "" EON SG_ STATE : 39|4@0+ (1,0) [0|15] "" EON - SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" EON - SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" EON + SG_ COUNTER : 32|4@1+ (1,0) [0|15] "" EON + SG_ CHECKSUM : 40|8@1+ (1,0) [0|255] "" EON BO_ 870 CURRENT_STATE: 4 EON SG_ ENABLED : 0|1@0+ (1,0) [0|0] "" HIM SG_ SET_SPEED : 15|8@0+ (1,0) [0|255] "mph" HIM SG_ CURRENT_SPEED : 23|8@0+ (1,0) [0|255] "kph" IBST - SG_ CHECKSUM_CTRLS : 31|8@0+ (1,0) [0|255] "" HIM + SG_ CHECKSUM : 24|8@1+ (1,0) [0|255] "" HIM BO_ 869 HIM_CTRLS: 3 HIM SG_ SPEEDDN_BTN : 3|1@0+ (1,0) [0|0] "" EON @@ -81,7 +81,7 @@ BO_ 869 HIM_CTRLS: 3 HIM SG_ CANCEL_BTN : 1|1@0+ (1,0) [0|0] "" EON SG_ SET_BTN : 0|1@0+ (1,0) [0|0] "" EON SG_ STATE : 11|4@0+ (1,0) [0|15] "" EON - SG_ CHECKSUM_CTRLS : 23|8@0+ (1,0) [0|255] "" EON + SG_ CHECKSUM : 16|8@1+ (1,0) [0|255] "" EON