Skip to content

Instantly share code, notes, and snippets.

@reinzor
Last active February 17, 2016 07:18
Show Gist options
  • Save reinzor/1ed4243785d1a27906fc to your computer and use it in GitHub Desktop.
Save reinzor/1ed4243785d1a27906fc to your computer and use it in GitHub Desktop.
Decode CAN signals
#include <stdint.h>
#include <iostream>
#define MASK32(nbits) ((0xffffffff)>> (32-nbits))
uint32_t extractSignal(const uint8_t* frame, const uint8_t startbit, const uint8_t length, bool is_big_endian)
{
uint8_t startByte = startbit / 8;
uint8_t startbit_in_byte = startbit % 8;
uint8_t end_byte = 0;
uint8_t count = 0;
uint8_t target = frame[startByte] >> startbit_in_byte;
uint8_t current_target_length = (8-startbit_in_byte);
if(is_big_endian) // Motorola (big endian)
{
end_byte = startByte - ((length-(8-startbit_in_byte))/8); // wow if this works???
for(count = startByte-1; count > end_byte; count --)
{
target |= frame[count] << current_target_length;
current_target_length += 8;
}
}
else // Intel (little endian)
{
end_byte = (startbit+length) / 8;
for(count = startByte+1; count < end_byte; count ++)
{
target |= frame[count] << current_target_length;
current_target_length += 8;
}
}
target &= MASK32(length);
return target;
}
float toPhysicalValue(uint32_t target, float factor, float offset, bool is_signed)
{
if (is_signed)
return ( (int32_t) target ) * factor + offset;
else
return target * factor + offset;
}
float decode(const uint8_t* frame, const uint16_t startbit, const uint16_t length, bool is_big_endian, bool is_signed, float factor, float offset)
{
return toPhysicalValue(extractSignal(frame, startbit, length, is_big_endian), factor, offset, is_signed);
}
void test(uint8_t* frame, uint8_t startbit, uint8_t length, bool is_big_endian, bool is_signed, float factor, float offset, uint32_t int_value, float value)
{
std::cout << "\n---- (startbit=" << (int) startbit << ",length=" << (int) length << ",is_big_endian=" << is_big_endian << ",is_signed=" << is_signed << ",factor=" << factor << ",offset=" << offset << ")" << std::endl;
std::cout << "Unsigned int value: " << extractSignal(frame, startbit, length, is_big_endian) << " should be " << int_value << std::endl;
std::cout << "Physical value: " << decode(frame, startbit, length, is_big_endian, is_signed, factor, offset) << " should be " << value << std::endl;
}
int main(void)
{
{
uint8_t src_array[8] = {48, 48, 48, 48, 225, 127, 202, 139};
test(src_array, 34, 2, true, false, 1.000000, 0, 0, 0.000000);
test(src_array, 40, 8, false, false, 0.010000, 0, 127, 1.270000);
test(src_array, 32, 1, false, false, 1.000000, 0, 1, 1.000000);
test(src_array, 16, 16, false, false, 0.003906, 0, 12336, 48.187500);
test(src_array, 0, 16, false, false, 0.000977, -31, 12336, -19.952148);
}
{
uint8_t src_array[8] = {13, 27, 78, 68, 254, 139, 13, 147};
test(src_array, 0, 2, true, false, 1.000000, 0, 1, 1.000000);
test(src_array, 2, 6, true, false, 1.000000, 0, 3, 3.000000);
test(src_array, 21, 11, true, false, 0.100000, 0, 218, 21.800000);
test(src_array, 25, 12, true, false, 0.062500, -128, 1826, -13.875000);
test(src_array, 32, 9, true, false, 0.062500, -16, 254, -0.125000);
test(src_array, 48, 3, true, false, 1.000000, 0, 5, 5.000000);
test(src_array, 51, 3, true, false, 1.000000, 0, 1, 1.000000);
test(src_array, 54, 10, true, false, 0.100000, -52, 556, 3.600000);
test(src_array, 56, 3, true, false, 1.000000, 0, 3, 3.000000);
test(src_array, 59, 3, true, false, 1.000000, 0, 2, 2.000000);
test(src_array, 62, 2, true, false, 1.000000, 0, 2, 2.000000);
}
return 0;
}
@ebroecker
Copy link

If I remember right, I coded the motorola-decoding with "most significant bit" in mind.
You can try this, if you use the startbit which is encoded in .dbc for motorola signals.
Maybe I'll have a look on this tomorrow.

PS: big endian (= motorola) signal-decoding is buggy currently.

PPS:
After review: big endian decoding needs "Least significant bit" as startbit.
But there is still a bug in the calculation of "end_byte", I'll have a look on in.

@ebroecker
Copy link

Please look at my fork,
decoding currently only has one error left...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment