Skip to content

Commit c4d55af

Browse files
committed
add support for big endian
1 parent e9e307e commit c4d55af

File tree

5 files changed

+57
-136
lines changed

5 files changed

+57
-136
lines changed

include/libdbc/dbc.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ namespace libdbc {
3535
std::vector<libdbc::Message> get_messages() const;
3636

3737
Message::ParseSignalsStatus parseMessage(const uint32_t id, const std::vector<uint8_t>& data, std::vector<double>& out_values);
38-
Message::ParseSignalsStatus parseMessage(const uint32_t id, const std::array<uint8_t, 8>& data, std::vector<double>& out_values);
39-
4038
void sortSignals();
4139

4240
private:

include/libdbc/message.hpp

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ namespace libdbc {
1313
explicit Message(uint32_t id, const std::string& name, uint8_t size, const std::string& node);
1414

1515
enum class ParseSignalsStatus {
16-
Success = 0,
17-
ErrorMessageToLong = -1,
18-
ErrorBigEndian = -2,
19-
ErrorUnknownID = -3,
16+
Success,
17+
ErrorMessageToLong,
18+
ErrorBigEndian,
19+
ErrorUnknownID,
20+
ErrorInvalidConversion,
2021
};
2122

2223
/*!
@@ -26,8 +27,6 @@ namespace libdbc {
2627
* \return
2728
*/
2829
ParseSignalsStatus parseSignals(const std::vector<uint8_t>& data, std::vector<double> &values) const;
29-
ParseSignalsStatus parseSignals(const std::array<uint8_t,8>& data, std::vector<double>& values) const;
30-
ParseSignalsStatus parseSignals(const uint8_t* data, int size, std::vector<double>& values) const;
3130

3231
void appendSignal(const Signal& signal);
3332
const std::vector<Signal> signals() const;
@@ -46,19 +45,7 @@ namespace libdbc {
4645
std::string m_name;
4746
uint8_t m_size;
4847
std::string m_node;
49-
std::vector<Signal> m_signals; // when changing this vector m_prepared must be set to false!
50-
51-
52-
bool m_prepared{false}; // indicates if the message is prepared for parsing signals
53-
struct BitStruct {
54-
BitStruct(uint32_t size): size(size), padding(true) {}
55-
BitStruct(int index, uint32_t size): index(index), size(size), padding(false) {}
56-
BitStruct() = delete;
57-
int index;
58-
uint32_t size;
59-
bool padding;
60-
};
61-
std::vector<BitStruct> bitstruct;
48+
std::vector<Signal> m_signals;
6249

6350
friend std::ostream& operator<<(std::ostream& os, const Message& dt);
6451
};

src/dbc.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,6 @@ namespace libdbc {
103103
return Message::ParseSignalsStatus::ErrorUnknownID;
104104
}
105105

106-
Message::ParseSignalsStatus DbcParser::parseMessage(const uint32_t id, const std::array<uint8_t, 8>& data, std::vector<double>& out_values) {
107-
for (const auto& message: messages) {
108-
if (message.id() == id)
109-
return message.parseSignals(data, out_values);
110-
}
111-
return Message::ParseSignalsStatus::ErrorUnknownID;
112-
}
113-
114-
115106
void DbcParser::parse_dbc_header(std::istream& file_stream) {
116107
std::string line;
117108
std::smatch match;

src/message.cpp

Lines changed: 17 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,16 @@ namespace libdbc {
1212
(m_size == rhs.m_size) && (m_node == rhs.m_node);
1313
}
1414

15-
Message::ParseSignalsStatus Message::parseSignals(const uint8_t* data, int size, std::vector<double>& values) const {
16-
// With the current approach it is not needed to prepare the message by sorting the signals
17-
// if (!m_prepared)
18-
// return false;
19-
15+
Message::ParseSignalsStatus Message::parseSignals(const std::vector<uint8_t>& data, std::vector<double>& values) const {
16+
int size = data.size();
2017
if (size > 8)
2118
return ParseSignalsStatus::ErrorMessageToLong; // not supported yet
2219

23-
// Currently only little endian will be supported, because
24-
// The code below was not tested with bigendian!
25-
// All signals must be little endian
26-
for (const auto& signal: m_signals) {
27-
if (signal.is_bigendian)
28-
return ParseSignalsStatus::ErrorBigEndian;
29-
}
30-
3120
uint64_t data_little_endian = 0;
3221
uint64_t data_big_endian = 0;
3322
for (int i=0; i < size; i++) {
3423
data_little_endian |= ((uint64_t)data[i]) << i * 8;
35-
//data_big_endian |= (uint64_t)data[i] << (size - 1 - i);
24+
data_big_endian = (data_big_endian << 8) | (uint64_t)data[i];
3625
}
3726

3827
// TODO: does this also work on a big endian machine?
@@ -41,30 +30,30 @@ namespace libdbc {
4130
uint64_t v = 0;
4231
for (const auto& signal: m_signals) {
4332
if (signal.is_bigendian) {
44-
// Not tested!
45-
// const uint32_t shiftLeft = signal.start_bit;
46-
// v = data_big_endian << shiftLeft;
47-
// v = v >> (shiftLeft + signal.start_bit);
33+
uint32_t start_bit = 8* (signal.start_bit / 8) + (7 - (signal.start_bit % 8)); // Calculation taken from python CAN
34+
v = data_big_endian << start_bit;
35+
v = v >> (len - signal.size);
4836
} else {
4937
const uint32_t shiftLeft = (len - (signal.size + signal.start_bit));
5038
v = data_little_endian << shiftLeft;
5139
v = v >> (shiftLeft + signal.start_bit);
5240
}
53-
values.push_back(v * signal.factor + signal.offset);
41+
42+
if (signal.is_signed && signal.size > 1) {
43+
switch (signal.size) {
44+
case 8: values.push_back((int8_t)v * signal.factor + signal.offset); break;
45+
case 16: values.push_back((int16_t)v * signal.factor + signal.offset); break;
46+
case 32: values.push_back((int32_t)v * signal.factor + signal.offset); break;
47+
case 64: values.push_back((int64_t)v * signal.factor + signal.offset); break;
48+
default: return ParseSignalsStatus::ErrorInvalidConversion;
49+
}
50+
} else
51+
values.push_back(v * signal.factor + signal.offset);
5452
}
5553
return ParseSignalsStatus::Success;
5654
}
5755

58-
Message::ParseSignalsStatus Message::parseSignals(const std::array<uint8_t,8>& data, std::vector<double>& values) const {
59-
return parseSignals(data.data(), data.size(), values);
60-
}
61-
62-
Message::ParseSignalsStatus Message::parseSignals(const std::vector<uint8_t> &data, std::vector<double>& values) const {
63-
return parseSignals(data.data(), data.size(), values);
64-
}
65-
6656
void Message::appendSignal(const Signal& signal) {
67-
m_prepared = false;
6857
m_signals.push_back(signal);
6958
}
7059

@@ -77,28 +66,7 @@ namespace libdbc {
7766
}
7867

7968
void Message::prepareMessage() {
80-
// m_prepared = false;
81-
// // sort signals so that the signals are ordered by the startbit
8269
std::sort(m_signals.begin(), m_signals.end());
83-
84-
// uint32_t curr_bit = 0;
85-
// for (std::vector<Signal>::size_type i=0; i < m_signals.size(); i++) {
86-
// const auto& signal = m_signals.at(i);
87-
// if (signal.is_multiplexed)
88-
// break; // Not supported yet
89-
90-
// if (curr_bit < signal.start_bit) {
91-
// // padding needed
92-
// bitstruct.push_back(BitStruct(signal.start_bit - curr_bit));
93-
// }
94-
// bitstruct.push_back(BitStruct(i, signal.size));
95-
// curr_bit = signal.start_bit + signal.size;
96-
// }
97-
// // Check if correct
98-
// if (curr_bit > m_size * 8)
99-
// return;
100-
101-
m_prepared = true;
10270
}
10371

10472
std::ostream& operator<< (std::ostream &out, const Message& msg) {

test/test_parseMessage.cpp

Lines changed: 34 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,7 @@
88

99
// Testing of parsing messages
1010

11-
TEST_CASE("Parse Message 1 Big Endian") {
12-
libdbc::DbcParser parser;
13-
14-
const auto dbcContent = R"(BO_ 234 MSG1: 8 Vector__XXX
15-
SG_ Sig1 : 0|8@0- (0.1,-3) [-3276.8|-3276.7] "C" Vector__XXX
16-
SG_ Sig2 : 8|8@0- (0.15,7) [-3276.8|-3276.7] "C" Vector__XXX
17-
)";
18-
19-
const auto* filename = std::tmpnam(NULL);
20-
CHECK(create_tmp_dbc_with(filename, dbcContent));
21-
22-
parser.parse_file(filename);
23-
24-
SECTION("Evaluating first message") {
25-
std::vector<double> out_values;
26-
CHECK(parser.parseMessage(234, std::vector<uint8_t>({0x01, 0x02}), out_values) == libdbc::Message::ParseSignalsStatus::ErrorBigEndian);
27-
// Big endian not supported
28-
// CHECK(out_values.size() == 2);
29-
// CHECK(out_values.at(0) == 0x01 * 0.1 - 3);
30-
// CHECK(out_values.at(1) == 0x02 * 0.15 + 7);
31-
}
32-
33-
}
34-
35-
TEST_CASE("Parse Message 2 Big Endian") {
11+
TEST_CASE("Parse Message Unknown ID") {
3612
libdbc::DbcParser parser;
3713

3814
const auto dbcContent = R"(BO_ 234 MSG1: 8 Vector__XXX
@@ -48,18 +24,6 @@ BO_ 123 MSG2: 8 Vector__XXX
4824

4925
parser.parse_file(filename);
5026

51-
SECTION("Evaluating first message") {
52-
std::vector<double> out_values;
53-
CHECK(parser.parseMessage(234, std::vector<uint8_t>({0x01, 0x02}), out_values) == libdbc::Message::ParseSignalsStatus::ErrorBigEndian);
54-
// Big endian not supported
55-
// std::vector<double> refData{0x01, 0x02};
56-
// CHECK(refData.size() == 2);
57-
// CHECK(out_values.size() == refData.size());
58-
// for (int i=0; i < refData.size(); i++) {
59-
// CHECK(out_values.at(i) == refData.at(i));
60-
// }
61-
}
62-
6327
SECTION("Evaluating unknown message id") {
6428
std::vector<double> out_values;
6529
CHECK(parser.parseMessage(578, std::vector<uint8_t>({0xFF, 0xA2}), out_values) == libdbc::Message::ParseSignalsStatus::ErrorUnknownID);
@@ -130,38 +94,51 @@ TEST_CASE("Parse Message little endian") {
13094

13195
libdbc::DbcParser p;
13296
p.parse_file(filename);
133-
p.sortSignals();
13497

13598
std::vector<uint8_t> data{0x08, 0x27, 0xa3, 0x22, 0xe5, 0x1f, 0x45, 0x14}; // little endian
13699
std::vector<double> result_values;
137100
REQUIRE(p.parseMessage(0x21d, data, result_values) == libdbc::Message::ParseSignalsStatus::Success);
138101
REQUIRE(result_values.size() == 4);
139-
REQUIRE(Catch::Approx(result_values.at(0)) == 99.92);
140-
REQUIRE(Catch::Approx(result_values.at(1)) == 88.67);
102+
103+
REQUIRE(Catch::Approx(result_values.at(0)) == 11.89);
104+
REQUIRE(Catch::Approx(result_values.at(1)) == 99.92);
141105
REQUIRE(Catch::Approx(result_values.at(2)) == 81.65);
142-
REQUIRE(Catch::Approx(result_values.at(3)) == 11.89);
106+
REQUIRE(Catch::Approx(result_values.at(3)) == 88.67);
143107
}
144108

145-
TEST_CASE("Parse Message big endian") {
109+
TEST_CASE("Parse Message big endian signed values") {
146110
const auto* filename = std::tmpnam(NULL);
147-
create_tmp_dbc_with(filename, R"(BO_ 541 STATUS: 8 DEVICE1
148-
SG_ Temperature : 48|16@0+ (0.01,-40) [-40|125] "C" DEVICE1
149-
SG_ SOH : 0|16@0+ (0.01,0) [0|100] "%" DEVICE1
150-
SG_ SOE : 32|16@0+ (0.01,0) [0|100] "%" DEVICE1
151-
SG_ SOC : 16|16@0+ (0.01,0) [0|100] "%" DEVICE1)");
111+
create_tmp_dbc_with(filename, R"(BO_ 545 MSG: 8 BMS2
112+
SG_ Sig1 : 62|1@0+ (1,0) [0|0] "" Vector__XXX
113+
SG_ Sig2 : 49|2@0+ (1,0) [0|0] "" Vector__XXX
114+
SG_ Sig3 : 39|16@0- (0.1,0) [0|0] "A" Vector__XXX
115+
SG_ Sig4 : 60|1@0+ (1,0) [0|0] "" Vector__XXX
116+
SG_ Sig5 : 55|1@0+ (1,0) [0|0] "" Vector__XXX
117+
SG_ Sig6 : 58|1@0+ (1,0) [0|0] "" Vector__XXX
118+
SG_ Sig7 : 59|1@0+ (1,0) [0|0] "" Vector__XXX
119+
SG_ Sig8 : 57|1@0+ (1,0) [0|0] "" Vector__XXX
120+
SG_ Sig9 : 56|1@0+ (1,0) [0|0] "" Vector__XXX
121+
SG_ Sig10 : 61|1@0+ (1,0) [0|0] "" Vector__XXX
122+
SG_ Sig11 : 7|16@0+ (0.001,0) [0|65.535] "V" Vector__XXX
123+
SG_ Sig12 : 23|16@0+ (0.1,0) [0|6553.5] "A" Vector__XXX)");
152124

153125
libdbc::DbcParser p;
154126
p.parse_file(filename);
155127

156-
std::vector<uint8_t> data{0x27, 0x08, 0x22, 0xa3, 0x1f, 0xe5, 0x14, 0x45}; // big endian
128+
std::vector<uint8_t> data{13, 177, 0, 216, 251, 180, 0, 31}; // big endian
157129
std::vector<double> result_values;
158-
REQUIRE(p.parseMessage(0x21d, data, result_values) == libdbc::Message::ParseSignalsStatus::ErrorBigEndian);
159-
// Big endian not yet supported
160-
// REQUIRE(result_values.size() == 4);
161-
// REQUIRE(Catch::Approx(result_values.at(0)) == 99.92);
162-
// REQUIRE(Catch::Approx(result_values.at(1)) == 88.67);
163-
// REQUIRE(Catch::Approx(result_values.at(2)) == 81.65);
164-
// REQUIRE(Catch::Approx(result_values.at(3)) == 11.89);
130+
REQUIRE(p.parseMessage(545, data, result_values) == libdbc::Message::ParseSignalsStatus::Success);
131+
REQUIRE(result_values.size() == 12);
132+
REQUIRE(Catch::Approx(result_values.at(0)) == 0);
133+
REQUIRE(Catch::Approx(result_values.at(1)) == 0);
134+
REQUIRE(Catch::Approx(result_values.at(2)) == -110);
135+
REQUIRE(Catch::Approx(result_values.at(3)) == 1);
136+
REQUIRE(Catch::Approx(result_values.at(4)) == 0);
137+
REQUIRE(Catch::Approx(result_values.at(5)) == 1);
138+
REQUIRE(Catch::Approx(result_values.at(6)) == 1);
139+
REQUIRE(Catch::Approx(result_values.at(7)) == 1);
140+
REQUIRE(Catch::Approx(result_values.at(8)) == 1);
141+
REQUIRE(Catch::Approx(result_values.at(9)) == 0);
142+
REQUIRE(Catch::Approx(result_values.at(10)) == 3.5050);
143+
REQUIRE(Catch::Approx(result_values.at(11)) == 21.6);
165144
}
166-
167-
// TODO: create also for big endian!

0 commit comments

Comments
 (0)