rusefi/firmware/util/efilib.h

163 lines
4.4 KiB
C++

/**
* @file efilib.h
*
* @date Feb 21, 2014
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#pragma once
#include <stdint.h>
#define _MAX_FILLER 11
// http://en.wikipedia.org/wiki/Endianness
static inline uint16_t SWAP_UINT16(uint16_t x)
{
return ((x << 8) | (x >> 8));
}
static inline uint32_t SWAP_UINT32(uint32_t x)
{
return (((x >> 24) & 0x000000ff) | ((x << 8) & 0x00ff0000) |
((x >> 8) & 0x0000ff00) | ((x << 24) & 0xff000000));
}
#define BIT(n) (UINT32_C(1) << (n))
// we also have efi::size which probably does not work for C code
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define HUMAN_OFFSET 1
// human-readable IDs start from 1 while computer-readable indices start from 0
#define ID2INDEX(id) ((id) - HUMAN_OFFSET)
// number of milliseconds in one period of given frequency (per second)
#define frequency2periodMs(freq) ((1000.0f) / (freq))
// number of microseconds in one period of given frequency (per second)
#define frequency2periodUs(freq) ((1000000.0f) / (freq))
#define ERROR_CODE 311223344
#define Q(x) #x
#define QUOTE(x) Q(x)
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
const char * boolToString(bool value);
char * efiTrim(char *param);
int mytolower(const char c);
uint32_t efiStrlen(const char *param);
int efiPow10(int param);
bool startsWith(const char *line, const char *prefix);
int indexOf(const char *string, char ch);
float atoff(const char *string);
int atoi(const char *string);
#define UNUSED(x) (void)(x)
int absI(int32_t value);
float absF(float value);
/**
* Rounds value to specified precision.
* @param precision some pow of 10 value - for example, 100 for two digit precision
*/
float efiRound(float value, float precision);
int maxI(int i1, int i2);
int minI(int i1, int i2);
float maxF(float i1, float i2);
float minF(float i1, float i2);
// sometimes known as 'itoa'
char* itoa10(char *p, int num);
bool isSameF(float v1, float v2);
int clampI(int min, int clamp, int max);
float clampF(float min, float clamp, float max);
/**
* clamps value into the [0, 100] range
*/
#define clampPercentValue(x) (clampF(0, x, 100))
bool strEqualCaseInsensitive(const char *str1, const char *str2);
bool strEqual(const char *str1, const char *str2);
// Currently used by air-interp. tCharge mode (see EngineState::updateTChargeK()).
float limitRateOfChange(float newValue, float oldValue, float incrLimitPerSec, float decrLimitPerSec, float secsPassed);
// @brief Compute e^x using a 4th order taylor expansion centered at x=-1. Provides
// bogus results outside the range -2 < x < 0.
float expf_taylor(float x);
// @brief Compute tan(theta) using a ratio of the Taylor series for sin and cos
// Valid for the range [0, pi/2 - 0.01]
float tanf_taylor(float theta);
#ifdef __cplusplus
}
#include <cstddef>
#include <cstring>
#define IS_NEGATIVE_ZERO(value) (__builtin_signbit(value) && value==0)
#define fixNegativeZero(value) (IS_NEGATIVE_ZERO(value) ? 0 : value)
// C++ helpers go here
namespace efi
{
template <typename T, size_t N>
constexpr size_t size(const T(&)[N]) {
return N;
}
// Zero the passed object
template <typename T>
constexpr void clear(T* obj) {
// The cast to void* is to prevent errors like:
// clearing an object of non-trivial type 'struct persistent_config_s'; use assignment or value-initialization instead
// This is technically wrong, but we know config objects only ever actually
// contain integral types, though they may be wrapped in a scaled_channel
memset(reinterpret_cast<void*>(obj), 0, sizeof(T));
}
template <typename T>
constexpr void clear(T& obj) {
clear(&obj);
}
} // namespace efi
#define assertIsInBounds(length, array, msg) efiAssertVoid(OBD_PCM_Processor_Fault, std::is_unsigned_v<decltype(length)> && (length) < efi::size(array), msg)
#define assertIsInBoundsWithResult(length, array, msg, failedResult) efiAssert(OBD_PCM_Processor_Fault, std::is_unsigned_v<decltype(length)> && (length) < efi::size(array), msg, failedResult)
template <typename T>
bool isInRange(T min, T val, T max) {
return val >= min && val <= max;
}
static constexpr size_t operator-(Gpio a, Gpio b) {
return (size_t)a - (size_t)b;
}
static constexpr Gpio operator-(Gpio a, size_t b) {
return (Gpio)((size_t)a - b);
}
static constexpr Gpio operator+(Gpio a, size_t b) {
return (Gpio)((size_t)a + b);
}
static constexpr Gpio operator+(size_t a, Gpio b) {
// addition is commutative, just use the other operator
return b + a;
}
#endif /* __cplusplus */