Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | /** | |||
2 | * @file efilib.cpp | |||
3 | * | |||
4 | * We cannot use stdlib because we do not have malloc - so, we have to implement these functions | |||
5 | * | |||
6 | * @date Feb 21, 2014 | |||
7 | * @author Andrey Belomutskiy, (c) 2012-2020 | |||
8 | */ | |||
9 | ||||
10 | #include "pch.h" | |||
11 | ||||
12 | #include <cstring> | |||
13 | #include <cctype> | |||
14 | #include <cmath> | |||
15 | #include "datalogging.h" | |||
16 | #include "histogram.h" | |||
17 | ||||
18 | // also known as bool2string and boolean2string | |||
19 | 196078 | const char * boolToString(bool value) { | ||
20 |
2/2✓ Branch 0 taken 5031 times.
✓ Branch 1 taken 191047 times.
|
196078 | return value ? "Yes" : "No"; | |
21 | } | |||
22 | ||||
23 | /* | |||
24 | float efiFloor(float value, float precision) { | |||
25 | int a = (int) (value / precision); | |||
26 | return a * precision; | |||
27 | } | |||
28 | */ | |||
29 | ||||
30 | /** | |||
31 | * | |||
32 | * @param precision for example '0.1' for one digit fractional part | |||
33 | */ | |||
34 | 657497 | float efiRound(float value, float precision) { | ||
35 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 657497 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 657497 times.
|
657497 | efiAssert(ObdCode::CUSTOM_ERR_ASSERT, precision != 0, "Zero precision is not valid for efiRound maybe you mean '1'?", NAN); |
36 | 657497 | float a = round(value / precision); | ||
37 |
4/4✓ Branch 0 taken 5295 times.
✓ Branch 1 taken 652202 times.
✓ Branch 2 taken 5293 times.
✓ Branch 3 taken 2 times.
|
657497 | return fixNegativeZero(a * precision); | |
38 | } | |||
39 | ||||
40 | 1 | char * efiTrim(char *param) { | ||
41 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
|
2/2✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1 time.
|
3 | while (param[0] == ' ') { |
42 | 2 | param++; // that would skip leading spaces | ||
43 | } | |||
44 | 1 | int len = std::strlen(param); | ||
45 |
3/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
|
0/1? Decision couldn't be analyzed.
|
3 | while (len > 0 && param[len - 1] == ' ') { |
46 | 2 | param[len - 1] = 0; | ||
47 | 2 | len--; | ||
48 | } | |||
49 | 1 | return param; | ||
50 | } | |||
51 | ||||
52 | 95297 | static char *ltoa_internal(char *p, uint32_t num, unsigned radix) { | ||
53 | 95297 | constexpr int bufferLength = 10; | ||
54 | ||||
55 | 95297 | char buffer[bufferLength]; | ||
56 | ||||
57 | 95297 | size_t idx = bufferLength - 1; | ||
58 | ||||
59 | // First, we write from right-to-left so that we don't have to compute | |||
60 | // log(num)/log(radix) | |||
61 | do | |||
62 | { | |||
63 | 275603 | auto digit = num % radix; | ||
64 | ||||
65 | // Digits 0-9 -> '0'-'9' | |||
66 | // Digits 10-15 -> 'a'-'f' | |||
67 |
1/2✓ Branch 0 taken 275603 times.
✗ Branch 1 not taken.
|
275603 | char c = digit < 10 | |
68 | 275603 | ? digit + '0' | ||
69 | ✗ | : digit + 'a' - 10; | ||
70 | ||||
71 | // Write this digit in to the buffer | |||
72 | 275603 | buffer[idx] = c; | ||
73 | 275603 | idx--; | ||
74 |
2/2✓ Branch 0 taken 180306 times.
✓ Branch 1 taken 95297 times.
|
2/2✓ Decision 'true' taken 180306 times.
✓ Decision 'false' taken 95297 times.
|
275603 | } while ((num /= radix) != 0); |
75 | ||||
76 | 95297 | idx++; | ||
77 | ||||
78 | // Now, we copy characters in to place in the final buffer | |||
79 |
2/2✓ Branch 0 taken 275603 times.
✓ Branch 1 taken 95297 times.
|
2/2✓ Decision 'true' taken 275603 times.
✓ Decision 'false' taken 95297 times.
|
370900 | while (idx < bufferLength) |
80 | { | |||
81 | 275603 | *p++ = buffer[idx++]; | ||
82 | } | |||
83 | ||||
84 | 95297 | return p; | ||
85 | } | |||
86 | ||||
87 | /** | |||
88 | * @return pointer at the end zero symbol after the digits | |||
89 | */ | |||
90 | 95297 | static char* itoa_signed(char *p, int num, unsigned radix) { | ||
91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 95297 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 95297 times.
|
95297 | if (num < 0) { |
92 | ✗ | *p++ = '-'; | ||
93 | ✗ | char *end = ltoa_internal(p, -num, radix); | ||
94 | ✗ | *end = 0; | ||
95 | ✗ | return end; | ||
96 | } | |||
97 | 95297 | char *end = ltoa_internal(p, num, radix); | ||
98 | 95297 | *end = 0; | ||
99 | 95297 | return end; | ||
100 | } | |||
101 | ||||
102 | /** | |||
103 | * Integer to string | |||
104 | * | |||
105 | * @return pointer at the end zero symbol after the digits | |||
106 | */ | |||
107 | 95297 | char* itoa10(char *p, int num) { | ||
108 | 95297 | return itoa_signed(p, num, 10); | ||
109 | } | |||
110 | ||||
111 | ✗ | int efiPow10(int param) { | ||
112 | ✗ | switch (param) { | ||
113 | ✗ | case 0: | ||
114 | ✗ | return 1; | ||
115 | ✗ | case 1: | ||
116 | ✗ | return 10; | ||
117 | ✗ | case 2: | ||
118 | ✗ | return 100; | ||
119 | ✗ | case 3: | ||
120 | ✗ | return 1000; | ||
121 | ✗ | case 4: | ||
122 | ✗ | return 10000; | ||
123 | ✗ | case 5: | ||
124 | ✗ | return 100000; | ||
125 | ✗ | case 6: | ||
126 | ✗ | return 1000000; | ||
127 | ✗ | case 7: | ||
128 | ✗ | return 10000000; | ||
129 | ✗ | case 8: | ||
130 | ✗ | return 100000000; | ||
131 | } | |||
132 | ✗ | return 10 * efiPow10(10 - 1); | ||
133 | } | |||
134 | ||||
135 | 16 | int djb2lowerCase(const char *str) { | ||
136 | 16 | unsigned long hash = 5381; | ||
137 | int c; | |||
138 | ||||
139 |
2/2✓ Branch 0 taken 209 times.
✓ Branch 1 taken 16 times.
|
2/2✓ Decision 'true' taken 209 times.
✓ Decision 'false' taken 16 times.
|
225 | while ( (c = *str++) ) { |
140 | 209 | c = std::tolower(c); | ||
141 | 209 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ | ||
142 | } | |||
143 | ||||
144 | 16 | return hash; | ||
145 | } | |||
146 | ||||
147 | /** | |||
148 | * @brief This function knows how to print a histogram_s summary | |||
149 | */ | |||
150 | ✗ | void printHistogram(Logging *logging, histogram_s *histogram) { | ||
151 | #if EFI_HISTOGRAMS && ! EFI_UNIT_TEST | |||
152 | int report[5]; | |||
153 | int len = hsReport(histogram, report); | |||
154 | ||||
155 | logging->reset(); | |||
156 | logging.append(PROTOCOL_MSG LOG_DELIMITER); | |||
157 | logging.appendPrintf("histogram %s *", histogram->name); | |||
158 | for (int i = 0; i < len; i++) | |||
159 | logging.appendPrintf("%d ", report[i]); | |||
160 | logging.appendPrintf("*"); | |||
161 | logging.append(LOG_DELIMITER); | |||
162 | scheduleLogging(logging); | |||
163 | #else | |||
164 | UNUSED(logging); | |||
165 | UNUSED(histogram); | |||
166 | ||||
167 | #endif /* EFI_HISTOGRAMS */ | |||
168 | ✗ | } | ||
169 | ||||
170 | 912 | float limitRateOfChange(float newValue, float oldValue, float incrLimitPerSec, float decrLimitPerSec, float secsPassed) { | ||
171 |
2/2✓ Branch 0 taken 901 times.
✓ Branch 1 taken 11 times.
|
2/2✓ Decision 'true' taken 901 times.
✓ Decision 'false' taken 11 times.
|
912 | if (newValue >= oldValue) |
172 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 901 times.
✓ Branch 5 taken 901 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 901 times.
✗ Branch 9 not taken.
|
901 | return (incrLimitPerSec <= 0.0f) ? newValue : oldValue + std::min(newValue - oldValue, incrLimitPerSec * secsPassed); | |
173 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 11 times.
✗ Branch 9 not taken.
|
11 | return (decrLimitPerSec <= 0.0f) ? newValue : oldValue - std::min(oldValue - newValue, decrLimitPerSec * secsPassed); | |
174 | } | |||
175 | ||||
176 | 245865 | bool isPhaseInRange(float test, float current, float next) { | ||
177 | 245865 | bool afterCurrent = test >= current; | ||
178 | 245865 | bool beforeNext = test < next; | ||
179 | ||||
180 |
2/2✓ Branch 0 taken 226142 times.
✓ Branch 1 taken 19723 times.
|
2/2✓ Decision 'true' taken 226142 times.
✓ Decision 'false' taken 19723 times.
|
245865 | if (next > current) { |
181 | // we're not near the end of the cycle, comparison is simple | |||
182 | // 0 |------------------------| 720 | |||
183 | // next current | |||
184 |
4/4✓ Branch 0 taken 145150 times.
✓ Branch 1 taken 80992 times.
✓ Branch 2 taken 19439 times.
✓ Branch 3 taken 125711 times.
|
226142 | return afterCurrent && beforeNext; | |
185 | } else { | |||
186 | // we're near the end of the cycle so we have to check the wraparound | |||
187 | // 0 -----------| |------ 720 | |||
188 | // next current | |||
189 | // Check whether test is after current (ie, between current tooth and end of cycle) | |||
190 | // or if test if before next (ie, between start of cycle and next tooth) | |||
191 |
4/4✓ Branch 0 taken 12851 times.
✓ Branch 1 taken 6872 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 12849 times.
|
19723 | return afterCurrent || beforeNext; | |
192 | } | |||
193 | } | |||
194 | ||||
195 | 43 | static int getBitRangeCommon(const uint8_t data[], int bitIndex, int bitWidth, int secondByteOffset) { | ||
196 | 43 | int byteIndex = bitIndex >> 3; | ||
197 | 43 | int shift = bitIndex - byteIndex * 8; | ||
198 | 43 | int value = data[byteIndex]; | ||
199 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 12 times.
|
2/2✓ Decision 'true' taken 31 times.
✓ Decision 'false' taken 12 times.
|
43 | if (shift + bitWidth > 8) { |
200 | 31 | value = value + data[secondByteOffset + byteIndex] * 256; | ||
201 | } | |||
202 | 43 | int mask = (1 << bitWidth) - 1; | ||
203 | 43 | return (value >> shift) & mask; | ||
204 | } | |||
205 | ||||
206 | // see also getBitRange in lua_lib.h | |||
207 | 5 | int getBitRangeLsb(const uint8_t data[], int bitIndex, int bitWidth) { | ||
208 | 5 | return getBitRangeCommon(data, bitIndex, bitWidth, 1); | ||
209 | } | |||
210 | ||||
211 | // see also getBitRangeMsb in lua_lib.h | |||
212 | 38 | int getBitRangeMsb(const uint8_t data[], int bitIndex, int bitWidth) { | ||
213 | 38 | return getBitRangeCommon(data, bitIndex, bitWidth, -1); | ||
214 | } | |||
215 | ||||
216 | 23 | void setBitRangeMsb(uint8_t data[], const int totalBitIndex, const int bitWidth, const int value) { | ||
217 | 23 | int leftBitWidh = bitWidth; | ||
218 | 23 | const int byteIndex = totalBitIndex >> 3; | ||
219 | 23 | const int bitInByteIndex = totalBitIndex - byteIndex * 8; | ||
220 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 13 times.
|
2/2✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 13 times.
|
23 | if (bitInByteIndex + leftBitWidh > 8) { |
221 | 10 | const int bitsToHandleNow = 8 - bitInByteIndex; | ||
222 | 10 | setBitRangeMsb(data, (byteIndex - 1) * 8, leftBitWidh - bitsToHandleNow, value >> bitsToHandleNow); | ||
223 | 10 | leftBitWidh = bitsToHandleNow; | ||
224 | } | |||
225 | 23 | const int mask = (1 << leftBitWidh) - 1; | ||
226 | 23 | data[byteIndex] = data[byteIndex] & (~(mask << bitInByteIndex)); | ||
227 | 23 | const int maskedValue = value & mask; | ||
228 | 23 | const int shiftedValue = maskedValue << bitInByteIndex; | ||
229 | 23 | data[byteIndex] = data[byteIndex] | shiftedValue; | ||
230 | 23 | } | ||
231 | ||||
232 | 46 | int motorolaMagicFromDbc(int b, int length) { | ||
233 | // https://github.com/ebroecker/canmatrix/wiki/signal-Byteorder | |||
234 | // convert from lsb0 bit numbering to msb0 bit numbering (or msb0 to lsb0) | |||
235 | 46 | b = b - (b % 8) + 7 - (b % 8); | ||
236 | // convert from lsbit of signal data to msbit of signal data, when bit numbering is msb0 | |||
237 | 46 | b = b + length - 1; | ||
238 | // convert from msbit of signal data to lsbit of signal data, when bit numbering is msb0 | |||
239 | 46 | b = b - (b % 8) + 7 - (b % 8); | ||
240 | 46 | return b; | ||
241 | } | |||
242 | ||||
243 | 20 | int getBitRangeMoto(const uint8_t data[], int bitIndex, int bitWidth) { | ||
244 | 20 | const int b = motorolaMagicFromDbc(bitIndex, bitWidth); | ||
245 | 20 | return getBitRangeMsb(data, b, bitWidth); | ||
246 | } | |||
247 | ||||
248 | 10 | void setBitRangeMoto(uint8_t data[], const int totalBitIndex, const int bitWidth, const int value) { | ||
249 | 10 | const int b = motorolaMagicFromDbc(totalBitIndex, bitWidth); | ||
250 | 10 | return setBitRangeMsb(data, b, bitWidth, value); | ||
251 | } | |||
252 |