rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
efilib.cpp
Go to the documentation of this file.
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
19const char * boolToString(bool value) {
20 return value ? "Yes" : "No";
21}
22
23/*
24float 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 */
34float efiRound(float value, float precision) {
35 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, precision != 0, "Zero precision is not valid for efiRound maybe you mean '1'?", NAN);
36 float a = round(value / precision);
37 return fixNegativeZero(a * precision);
38}
39
40char * efiTrim(char *param) {
41 while (param[0] == ' ') {
42 param++; // that would skip leading spaces
43 }
44 int len = std::strlen(param);
45 while (len > 0 && param[len - 1] == ' ') {
46 param[len - 1] = 0;
47 len--;
48 }
49 return param;
50}
51
52static char *ltoa_internal(char *p, uint32_t num, unsigned radix) {
53 constexpr int bufferLength = 10;
54
55 char buffer[bufferLength];
56
57 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 auto digit = num % radix;
64
65 // Digits 0-9 -> '0'-'9'
66 // Digits 10-15 -> 'a'-'f'
67 char c = digit < 10
68 ? digit + '0'
69 : digit + 'a' - 10;
70
71 // Write this digit in to the buffer
72 buffer[idx] = c;
73 idx--;
74 } while ((num /= radix) != 0);
75
76 idx++;
77
78 // Now, we copy characters in to place in the final buffer
79 while (idx < bufferLength)
80 {
81 *p++ = buffer[idx++];
82 }
83
84 return p;
85}
86
87/**
88 * @return pointer at the end zero symbol after the digits
89 */
90static char* itoa_signed(char *p, int num, unsigned radix) {
91 if (num < 0) {
92 *p++ = '-';
93 char *end = ltoa_internal(p, -num, radix);
94 *end = 0;
95 return end;
96 }
97 char *end = ltoa_internal(p, num, radix);
98 *end = 0;
99 return end;
100}
101
102/**
103 * Integer to string
104 *
105 * @return pointer at the end zero symbol after the digits
106 */
107char* itoa10(char *p, int num) {
108 return itoa_signed(p, num, 10);
109}
110
111int 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
135int djb2lowerCase(const char *str) {
136 unsigned long hash = 5381;
137 int c;
138
139 while ( (c = *str++) ) {
140 c = std::tolower(c);
141 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
142 }
143
144 return hash;
145}
146
147/**
148 * @brief This function knows how to print a histogram_s summary
149 */
150void 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
170float limitRateOfChange(float newValue, float oldValue, float incrLimitPerSec, float decrLimitPerSec, float secsPassed) {
171 if (newValue >= oldValue)
172 return (incrLimitPerSec <= 0.0f) ? newValue : oldValue + std::min(newValue - oldValue, incrLimitPerSec * secsPassed);
173 return (decrLimitPerSec <= 0.0f) ? newValue : oldValue - std::min(oldValue - newValue, decrLimitPerSec * secsPassed);
174}
175
176bool isPhaseInRange(float test, float current, float next) {
177 bool afterCurrent = test >= current;
178 bool beforeNext = test < next;
179
180 if (next > current) {
181 // we're not near the end of the cycle, comparison is simple
182 // 0 |------------------------| 720
183 // next current
184 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 return afterCurrent || beforeNext;
192 }
193}
194
195static uint32_t getBitRangeCommon(const uint8_t data[], int bitIndex, int bitWidth, int secondByteOffset) {
196 int byteIndex = bitIndex >> 3;
197 int shift = bitIndex - byteIndex * 8;
198 uint32_t value = 0;
199 uint32_t dataShift = 0;
200 int remainWidth = shift + bitWidth;
201 while (remainWidth > 0) {
202 value += data[byteIndex] << dataShift;
203 byteIndex += secondByteOffset;
204 dataShift += 8;
205 remainWidth -= 8;
206 }
207 uint32_t mask = (uint64_t(1) << bitWidth) - 1;
208 return (value >> shift) & mask;
209}
210
211// see also getBitRange in lua_lib.h
212uint32_t getBitRangeLsb(const uint8_t data[], int bitIndex, int bitWidth) {
213 return getBitRangeCommon(data, bitIndex, bitWidth, 1);
214}
215
216// see also getBitRangeMsb in lua_lib.h
217uint32_t getBitRangeMsb(const uint8_t data[], int bitIndex, int bitWidth) {
218 return getBitRangeCommon(data, bitIndex, bitWidth, -1);
219}
220
221void setBitRangeLsb(uint8_t data[], const int totalBitIndex, const int bitWidth, const uint32_t value) {
222 int leftBitWidth = bitWidth;
223 const int byteIndex = totalBitIndex >> 3;
224 const int bitInByteIndex = totalBitIndex - byteIndex * 8;
225 if (bitInByteIndex + bitWidth > 8) {
226 const int bitsToHandleNow = 8 - bitInByteIndex;
227 setBitRangeLsb(data, totalBitIndex + bitsToHandleNow, leftBitWidth - bitsToHandleNow, value >> bitsToHandleNow);
228 leftBitWidth = bitsToHandleNow;
229 }
230 uint32_t mask = (uint64_t(1) << leftBitWidth) - 1;
231 data[byteIndex] = data[byteIndex] & (~(mask << bitInByteIndex));
232 const uint32_t maskedValue = value & mask;
233 const uint32_t shiftedValue = maskedValue << bitInByteIndex;
234 data[byteIndex] = data[byteIndex] | shiftedValue;
235}
236
237void setBitRangeMsb(uint8_t data[], const int totalBitIndex, const int bitWidth, const uint32_t value) {
238 int leftBitWidh = bitWidth;
239 const int byteIndex = totalBitIndex >> 3;
240 const int bitInByteIndex = totalBitIndex - byteIndex * 8;
241 if (bitInByteIndex + leftBitWidh > 8) {
242 const int bitsToHandleNow = 8 - bitInByteIndex;
243 setBitRangeMsb(data, (byteIndex - 1) * 8, leftBitWidh - bitsToHandleNow, value >> bitsToHandleNow);
244 leftBitWidh = bitsToHandleNow;
245 }
246 const uint32_t mask = (uint64_t(1) << leftBitWidh) - 1;
247 data[byteIndex] = data[byteIndex] & (~(mask << bitInByteIndex));
248 const uint32_t maskedValue = value & mask;
249 const uint32_t shiftedValue = maskedValue << bitInByteIndex;
250 data[byteIndex] = data[byteIndex] | shiftedValue;
251}
252
253int motorolaMagicFromDbc(int b, int length) {
254 // https://github.com/ebroecker/canmatrix/wiki/signal-Byteorder
255 // convert from lsb0 bit numbering to msb0 bit numbering (or msb0 to lsb0)
256 b = b - (b % 8) + 7 - (b % 8);
257 // convert from lsbit of signal data to msbit of signal data, when bit numbering is msb0
258 b = b + length - 1;
259 // convert from msbit of signal data to lsbit of signal data, when bit numbering is msb0
260 b = b - (b % 8) + 7 - (b % 8);
261 return b;
262}
263
264uint32_t getBitRangeMoto(const uint8_t data[], int bitIndex, int bitWidth) {
265 const int b = motorolaMagicFromDbc(bitIndex, bitWidth);
266 return getBitRangeMsb(data, b, bitWidth);
267}
268
269void setBitRangeMoto(uint8_t data[], const int totalBitIndex, const int bitWidth, const uint32_t value) {
270 const int b = motorolaMagicFromDbc(totalBitIndex, bitWidth);
271 return setBitRangeMsb(data, b, bitWidth, value);
272}
void reset()
void appendPrintf(const char *fmt,...) __attribute__((format(printf
Buffered console output stream header.
float limitRateOfChange(float newValue, float oldValue, float incrLimitPerSec, float decrLimitPerSec, float secsPassed)
Definition efilib.cpp:170
int djb2lowerCase(const char *str)
Definition efilib.cpp:135
uint32_t getBitRangeMoto(const uint8_t data[], int bitIndex, int bitWidth)
Definition efilib.cpp:264
int motorolaMagicFromDbc(int b, int length)
Definition efilib.cpp:253
const char * boolToString(bool value)
Definition efilib.cpp:19
void setBitRangeLsb(uint8_t data[], const int totalBitIndex, const int bitWidth, const uint32_t value)
Definition efilib.cpp:221
void setBitRangeMsb(uint8_t data[], const int totalBitIndex, const int bitWidth, const uint32_t value)
Definition efilib.cpp:237
bool isPhaseInRange(float test, float current, float next)
Definition efilib.cpp:176
float efiRound(float value, float precision)
Definition efilib.cpp:34
void printHistogram(Logging *logging, histogram_s *histogram)
This function knows how to print a histogram_s summary.
Definition efilib.cpp:150
static char * ltoa_internal(char *p, uint32_t num, unsigned radix)
Definition efilib.cpp:52
static char * itoa_signed(char *p, int num, unsigned radix)
Definition efilib.cpp:90
static uint32_t getBitRangeCommon(const uint8_t data[], int bitIndex, int bitWidth, int secondByteOffset)
Definition efilib.cpp:195
uint32_t getBitRangeLsb(const uint8_t data[], int bitIndex, int bitWidth)
Definition efilib.cpp:212
char * efiTrim(char *param)
Definition efilib.cpp:40
char * itoa10(char *p, int num)
Definition efilib.cpp:107
int efiPow10(int param)
Definition efilib.cpp:111
uint32_t getBitRangeMsb(const uint8_t data[], int bitIndex, int bitWidth)
Definition efilib.cpp:217
void setBitRangeMoto(uint8_t data[], const int totalBitIndex, const int bitWidth, const uint32_t value)
Definition efilib.cpp:269
union test_buffers test
Definition test.c:50
int hsReport(histogram_s *h, int *report)
Prepare histogram report.
This data structure is used to analyze CPU performance.
UNUSED(samplingTimeSeconds)
void scheduleLogging(Logging *logging)
@ CUSTOM_ERR_ASSERT
char name[16]
Definition histogram.h:28
static BigBufferHandle buffer
static tstrWifiInitParam param