2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file table_helper.h
|
|
|
|
*
|
|
|
|
* @date Jul 6, 2014
|
2020-01-13 18:57:43 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
2020-04-01 18:32:21 -07:00
|
|
|
|
|
|
|
#pragma once
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include "error_handling.h"
|
|
|
|
#include "interpolation.h"
|
2015-12-27 09:01:53 -08:00
|
|
|
#include "efilib.h"
|
2020-09-10 15:44:10 -07:00
|
|
|
#include "efi_ratio.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-06-10 09:38:32 -07:00
|
|
|
// popular left edge of CLT-based correction curves
|
2019-05-25 10:36:29 -07:00
|
|
|
#define CLT_CURVE_RANGE_FROM -40
|
|
|
|
|
2019-07-12 05:31:38 -07:00
|
|
|
class ValueProvider3D {
|
|
|
|
public:
|
2020-03-18 18:55:46 -07:00
|
|
|
virtual float getValue(float xRpm, float y) const = 0;
|
2019-07-12 05:31:38 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-01-18 09:03:32 -08:00
|
|
|
/**
|
|
|
|
* this helper class brings together 3D table with two 2D axis curves
|
|
|
|
*/
|
2020-09-10 15:44:10 -07:00
|
|
|
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE, typename vType, typename kType, typename TValueMultiplier = efi::ratio<1>>
|
2019-07-12 05:31:38 -07:00
|
|
|
class Map3D : public ValueProvider3D {
|
2015-07-10 06:01:56 -07:00
|
|
|
public:
|
2020-09-10 19:03:16 -07:00
|
|
|
explicit Map3D(const char*name) {
|
|
|
|
create(name);
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-09-10 19:03:16 -07:00
|
|
|
void init(vType table[RPM_BIN_SIZE][LOAD_BIN_SIZE], const kType loadBins[LOAD_BIN_SIZE], const kType rpmBins[RPM_BIN_SIZE]) {
|
|
|
|
// this method cannot use logger because it's invoked before everything
|
|
|
|
// that's because this method needs to be invoked before initial configuration processing
|
|
|
|
// and initial configuration load is done prior to logging initialization
|
|
|
|
for (int k = 0; k < LOAD_BIN_SIZE; k++) {
|
|
|
|
pointers[k] = table[k];
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2020-09-10 19:03:16 -07:00
|
|
|
this->loadBins = loadBins;
|
|
|
|
this->rpmBins = rpmBins;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
2016-04-15 20:01:40 -07:00
|
|
|
|
2020-09-10 19:03:16 -07:00
|
|
|
float getValue(float xRpm, float y) const override {
|
|
|
|
efiAssert(CUSTOM_ERR_ASSERT, loadBins, "map not initialized", NAN);
|
|
|
|
if (cisnan(y)) {
|
|
|
|
warning(CUSTOM_PARAM_RANGE, "%s: y is NaN", name);
|
|
|
|
return NAN;
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-09-10 19:03:16 -07:00
|
|
|
// todo: we have a bit of a mess: in TunerStudio, RPM is X-axis
|
2021-04-08 13:14:06 -07:00
|
|
|
return interpolate3d<vType, kType>(name, y, loadBins, LOAD_BIN_SIZE, xRpm, rpmBins, RPM_BIN_SIZE, pointers) * TValueMultiplier::asFloat();
|
2015-12-27 09:01:53 -08:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-09-10 19:03:16 -07:00
|
|
|
void setAll(vType value) {
|
|
|
|
efiAssertVoid(CUSTOM_ERR_6573, loadBins, "map not initialized");
|
|
|
|
for (int l = 0; l < LOAD_BIN_SIZE; l++) {
|
|
|
|
for (int r = 0; r < RPM_BIN_SIZE; r++) {
|
|
|
|
pointers[l][r] = value / TValueMultiplier::asFloat();
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
}
|
2020-09-10 19:03:16 -07:00
|
|
|
|
|
|
|
vType *pointers[LOAD_BIN_SIZE];
|
|
|
|
private:
|
|
|
|
void create(const char* name) {
|
|
|
|
this->name = name;
|
|
|
|
memset(&pointers, 0, sizeof(pointers));
|
|
|
|
}
|
|
|
|
|
|
|
|
const kType *loadBins = NULL;
|
|
|
|
const kType *rpmBins = NULL;
|
|
|
|
const char *name;
|
|
|
|
};
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-09-10 15:44:10 -07:00
|
|
|
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE, typename vType, typename kType, typename TValueMultiplier = efi::ratio<1>>
|
2016-07-02 15:02:12 -07:00
|
|
|
void copy2DTable(const vType source[LOAD_BIN_SIZE][RPM_BIN_SIZE], vType destination[LOAD_BIN_SIZE][RPM_BIN_SIZE]) {
|
|
|
|
for (int k = 0; k < LOAD_BIN_SIZE; k++) {
|
|
|
|
for (int rpmIndex = 0; rpmIndex < RPM_BIN_SIZE; rpmIndex++) {
|
|
|
|
destination[k][rpmIndex] = source[k][rpmIndex];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-26 15:15:17 -07:00
|
|
|
typedef Map3D<FUEL_RPM_COUNT, FUEL_LOAD_COUNT, uint8_t, float, efi::ratio<1, PACK_MULT_LAMBDA_CFG>> lambda_Map3D_t;
|
2019-06-10 09:38:32 -07:00
|
|
|
typedef Map3D<IGN_RPM_COUNT, IGN_LOAD_COUNT, float, float> ign_Map3D_t;
|
|
|
|
typedef Map3D<FUEL_RPM_COUNT, FUEL_LOAD_COUNT, float, float> fuel_Map3D_t;
|
|
|
|
typedef Map3D<BARO_CORR_SIZE, BARO_CORR_SIZE, float, float> baroCorr_Map3D_t;
|
2019-06-15 11:11:38 -07:00
|
|
|
typedef Map3D<PEDAL_TO_TPS_SIZE, PEDAL_TO_TPS_SIZE, uint8_t, uint8_t> pedal2tps_t;
|
2020-09-10 15:44:10 -07:00
|
|
|
typedef Map3D<BOOST_RPM_COUNT, BOOST_LOAD_COUNT, uint8_t, uint8_t, efi::ratio<LOAD_1_BYTE_PACKING_MULT>> boostOpenLoop_Map3D_t;
|
2020-01-31 11:23:15 -08:00
|
|
|
typedef Map3D<BOOST_RPM_COUNT, BOOST_LOAD_COUNT, uint8_t, uint8_t> boostClosedLoop_Map3D_t;
|
2019-12-03 21:37:32 -08:00
|
|
|
typedef Map3D<IAC_PID_MULT_SIZE, IAC_PID_MULT_SIZE, uint8_t, uint8_t> iacPidMultiplier_t;
|
2020-04-26 11:06:28 -07:00
|
|
|
typedef Map3D<GPPWM_RPM_COUNT, GPPWM_LOAD_COUNT, uint8_t, uint8_t> gppwm_Map3D_t;
|
2021-01-31 14:19:06 -08:00
|
|
|
typedef Map3D<FUEL_RPM_COUNT, FUEL_LOAD_COUNT, uint16_t, uint16_t, efi::ratio<1, PACK_MULT_MAP_ESTIMATE>> mapEstimate_Map3D_t;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2016-01-21 18:03:08 -08:00
|
|
|
void setRpmBin(float array[], int size, float idleRpm, float topRpm);
|
|
|
|
|
2019-06-10 20:27:54 -07:00
|
|
|
/**
|
2019-11-22 20:27:24 -08:00
|
|
|
* @param precision for example '0.1' for one digit fractional part. Default to 0.01, two digits.
|
2019-06-10 20:27:54 -07:00
|
|
|
*/
|
2019-11-22 20:27:24 -08:00
|
|
|
template<typename TValue, int TSize>
|
|
|
|
void setLinearCurve(TValue (&array)[TSize], float from, float to, float precision = 0.01f) {
|
|
|
|
for (int i = 0; i < TSize; i++) {
|
|
|
|
float value = interpolateMsg("setLinearCurve", 0, from, TSize - 1, to, i);
|
|
|
|
|
2019-06-10 20:27:54 -07:00
|
|
|
/**
|
|
|
|
* rounded values look nicer, also we want to avoid precision mismatch with Tuner Studio
|
|
|
|
*/
|
|
|
|
array[i] = efiRound(value, precision);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-22 20:27:24 -08:00
|
|
|
template<typename TValue, int TSize>
|
|
|
|
void setArrayValues(TValue (&array)[TSize], TValue value) {
|
|
|
|
for (int i = 0; i < TSize; i++) {
|
|
|
|
array[i] = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-21 21:57:11 -07:00
|
|
|
template <typename TElement, size_t N, size_t M>
|
|
|
|
constexpr void setTable(TElement (&dest)[N][M], const TElement value) {
|
|
|
|
for (size_t n = 0; n < N; n++) {
|
|
|
|
for (size_t m = 0; m < M; m++) {
|
|
|
|
dest[n][m] = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
void setRpmTableBin(float array[], int size);
|