fome-fw/firmware/controllers/core/fsio_impl.cpp

419 lines
12 KiB
C++
Raw Normal View History

2014-12-27 13:03:38 -08:00
/**
* @file fsio_impl.cpp
* @brief FSIO as it's used for GPIO
*
* @date Oct 5, 2014
2015-01-12 15:04:10 -08:00
* @author Andrey Belomutskiy, (c) 2012-2015
2014-12-27 13:03:38 -08:00
*/
#include "main.h"
#if EFI_FSIO || defined(__DOXYGEN__)
#include "fsio_impl.h"
#include "allsensors.h"
#include "rpm_calculator.h"
#include "efiGpio.h"
/**
* Here we define all rusEfi-specific methods
*/
static LENameOrdinalPair leRpm(LE_METHOD_RPM, "rpm");
static LENameOrdinalPair leTps(LE_METHOD_TPS, "tps");
static LENameOrdinalPair leMaf(LE_METHOD_MAF, "maf");
static LENameOrdinalPair leVBatt(LE_METHOD_VBATT, "vbatt");
static LENameOrdinalPair leFan(LE_METHOD_FAN, "fan");
static LENameOrdinalPair leCoolant(LE_METHOD_COOLANT, "coolant");
static LENameOrdinalPair leAcToggle(LE_METHOD_AC_TOGGLE, "ac_on_switch");
2015-01-15 13:03:51 -08:00
static LENameOrdinalPair leFanOnSetting(LE_METHOD_FAN_ON_SETTING,
"fan_on_setting");
static LENameOrdinalPair leFanOffSetting(LE_METHOD_FAN_OFF_SETTING,
"fan_off_setting");
static LENameOrdinalPair leTimeSinceBoot(LE_METHOD_TIME_SINCE_BOOT,
"time_since_boot");
2014-12-27 13:03:38 -08:00
static LENameOrdinalPair leFsioSsetting(LE_METHOD_FSIO_SETTING, "fsio_setting");
#define LE_EVAL_POOL_SIZE 32
2015-01-12 20:03:39 -08:00
extern engine_pins_s enginePins;
2014-12-27 13:03:38 -08:00
static LECalculator evalCalc;
static LEElement evalPoolElements[LE_EVAL_POOL_SIZE];
static LEElementPool evalPool(evalPoolElements, LE_EVAL_POOL_SIZE);
#define SYS_ELEMENT_POOL_SIZE 128
#define UD_ELEMENT_POOL_SIZE 128
static LEElement sysElements[SYS_ELEMENT_POOL_SIZE];
LEElementPool sysPool(sysElements, SYS_ELEMENT_POOL_SIZE);
static LEElement userElements[UD_ELEMENT_POOL_SIZE];
LEElementPool userPool(userElements, UD_ELEMENT_POOL_SIZE);
static LEElement * fsioLogics[LE_COMMAND_COUNT] CCM_OPTIONAL;
static LEElement * acRelayLogic;
static LEElement * fuelPumpLogic;
static LEElement * radiatorFanLogic;
static LEElement * alternatorLogic;
2015-01-15 13:03:51 -08:00
EXTERN_ENGINE
;
2014-12-27 14:03:37 -08:00
#if EFI_PROD_CODE || EFI_SIMULATOR
2015-01-14 17:06:02 -08:00
static Logging *logger;
2014-12-27 14:03:37 -08:00
float getLEValue(Engine *engine, calc_stack_t *s, le_action_e action) {
efiAssert(engine!=NULL, "getLEValue", NAN);
switch (action) {
case LE_METHOD_FAN:
2015-01-12 20:03:39 -08:00
return enginePins.fanRelay.getLogicValue();
2014-12-27 14:03:37 -08:00
case LE_METHOD_AC_TOGGLE:
return getAcToggle(engine);
case LE_METHOD_COOLANT:
return getCoolantTemperature(engine);
case LE_METHOD_INTAKE_AIR:
return getIntakeAirTemperature(engine);
case LE_METHOD_RPM:
return engine->rpmCalculator.rpm();
case LE_METHOD_TIME_SINCE_BOOT:
return getTimeNowSeconds();
case LE_METHOD_FAN_OFF_SETTING:
return engine->engineConfiguration->fanOffTemperature;
case LE_METHOD_FAN_ON_SETTING:
return engine->engineConfiguration->fanOnTemperature;
case LE_METHOD_VBATT:
return getVBatt(engine->engineConfiguration);
default:
firmwareError("FSIO unexpected %d", action);
return NAN;
}
}
#endif
#if EFI_PROD_CODE || defined(__DOXYGEN__)
#include "pin_repository.h"
#include "pwm_generator.h"
// todo: that's about bench test mode, wrong header for sure!
#include "injector_central.h"
static void setFsioPin(const char *indexStr, const char *pinName) {
int index = atoi(indexStr) - 1;
if (index < 0 || index >= LE_COMMAND_COUNT) {
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "invalid index %d", index);
2014-12-27 14:03:37 -08:00
return;
}
brain_pin_e pin = parseBrainPin(pinName);
// todo: extract method - code duplication with other 'set_xxx_pin' methods?
if (pin == GPIO_INVALID) {
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "invalid pin name [%s]", pinName);
2014-12-27 14:03:37 -08:00
return;
}
boardConfiguration->fsioPins[index] = pin;
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "FSIO pin #%d [%s]", (index + 1), hwPortname(pin));
2014-12-27 14:03:37 -08:00
}
#endif
2015-01-15 13:03:51 -08:00
void setFsioExt(engine_configuration_s *engineConfiguration, int index,
brain_pin_e pin, const char * exp, int freq) {
2014-12-27 13:03:38 -08:00
board_configuration_s *boardConfiguration = &engineConfiguration->bc;
boardConfiguration->fsioPins[index] = pin;
strcpy(boardConfiguration->le_formulas[index], exp);
boardConfiguration->fsioFrequency[index] = freq;
}
2015-01-15 13:03:51 -08:00
void setFsio(engine_configuration_s *engineConfiguration, int index,
brain_pin_e pin, const char * exp) {
2014-12-27 13:03:38 -08:00
setFsioExt(engineConfiguration, index, pin, exp, 0);
}
void applyFsioConfiguration(DECLARE_ENGINE_PARAMETER_F) {
board_configuration_s * boardConfiguration = &engineConfiguration->bc;
for (int i = 0; i < LE_COMMAND_COUNT; i++) {
brain_pin_e brainPin = boardConfiguration->fsioPins[i];
if (brainPin != GPIO_UNASSIGNED) {
const char *formula = boardConfiguration->le_formulas[i];
LEElement *logic = userPool.parseExpression(formula);
if (logic == NULL) {
warning(OBD_PCM_Processor_Fault, "parsing [%s]", formula);
}
fsioLogics[i] = logic;
}
}
}
2014-12-27 14:03:37 -08:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2014-12-27 13:03:38 -08:00
static SimplePwm fsioPwm[LE_COMMAND_COUNT] CCM_OPTIONAL;
static LECalculator calc;
extern LEElement * fsioLogics[LE_COMMAND_COUNT];
2015-01-12 20:03:39 -08:00
// that's crazy, but what's an alternative? we need const char *, a shared buffer would not work for pin repository
static const char *getGpioPinName(int index) {
2015-01-15 13:03:51 -08:00
switch (index) {
case 0:
return "GPIO_0";
case 1:
return "GPIO_1";
case 10:
return "GPIO_10";
case 11:
return "GPIO_11";
case 12:
return "GPIO_12";
case 13:
return "GPIO_13";
case 14:
return "GPIO_14";
case 15:
return "GPIO_15";
case 2:
return "GPIO_2";
case 3:
return "GPIO_3";
case 4:
return "GPIO_4";
case 5:
return "GPIO_5";
case 6:
return "GPIO_6";
case 7:
return "GPIO_7";
case 8:
return "GPIO_8";
case 9:
return "GPIO_9";
}
return NULL;
2015-01-12 20:03:39 -08:00
}
2015-01-15 13:03:51 -08:00
static OutputPin fsioOutputs[LE_COMMAND_COUNT];
2014-12-27 13:03:38 -08:00
static void handleFsio(Engine *engine, int index) {
if (boardConfiguration->fsioPins[index] == GPIO_UNASSIGNED)
return;
bool_t isPwmMode = boardConfiguration->fsioFrequency[index] != 0;
float fvalue = calc.getValue2(fsioLogics[index], engine);
engine->engineConfiguration2->fsioLastValue[index] = fvalue;
if (isPwmMode) {
fsioPwm[index].setSimplePwmDutyCycle(fvalue);
} else {
int value = (int) fvalue;
2015-01-15 13:03:51 -08:00
if (value != fsioOutputs[index].getLogicValue()) {
2015-01-14 17:06:02 -08:00
// scheduleMsg(logger, "setting %s %s", getIo_pin_e(pin), boolToString(value));
2015-01-15 13:03:51 -08:00
fsioOutputs[index].setValue(value);
2014-12-27 13:03:38 -08:00
}
}
}
2015-01-15 13:03:51 -08:00
static void setPinState(const char * msg, OutputPin *pin, LEElement *element,
Engine *engine) {
2014-12-27 13:03:38 -08:00
if (element == NULL) {
2015-01-12 20:03:39 -08:00
warning(OBD_PCM_Processor_Fault, "invalid expression for %s", msg);
2014-12-27 13:03:38 -08:00
} else {
int value = calc.getValue2(element, engine);
2015-01-12 20:03:39 -08:00
if (value != pin->getLogicValue()) {
2014-12-27 13:03:38 -08:00
if (isRunningBenchTest())
return; // let's not mess with bench testing
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "setting %s %s", msg, boolToString(value));
2015-01-12 20:03:39 -08:00
pin->setValue(value);
2014-12-27 13:03:38 -08:00
}
}
}
static void showFsio(const char *msg, LEElement *element) {
if (msg != NULL)
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "%s:", msg);
2014-12-27 13:03:38 -08:00
while (element != NULL) {
2015-01-15 13:03:51 -08:00
scheduleMsg(logger, "action %d: fValue=%f iValue=%d", element->action,
element->fValue, element->iValue);
2014-12-27 13:03:38 -08:00
element = element->next;
}
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "<end>");
2014-12-27 13:03:38 -08:00
}
static void showFsioInfo(void) {
2015-01-15 13:03:51 -08:00
scheduleMsg(logger, "sys used %d/user used %d", sysPool.getSize(),
userPool.getSize());
2014-12-27 13:03:38 -08:00
showFsio("a/c", acRelayLogic);
showFsio("fuel", fuelPumpLogic);
showFsio("fan", radiatorFanLogic);
showFsio("alt", alternatorLogic);
for (int i = 0; i < LE_COMMAND_COUNT; i++) {
char * exp = boardConfiguration->le_formulas[i];
if (exp[0] != 0) {
/**
* in case of FSIO user interface indexes are starting with 0, the argument for that
* is the fact that the target audience is more software developers
*/
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "FSIO #%d [%s] at %s@%dHz value=%f", i, exp,
2015-01-15 13:03:51 -08:00
hwPortname(boardConfiguration->fsioPins[i]),
boardConfiguration->fsioFrequency[i],
2014-12-27 13:03:38 -08:00
engineConfiguration2->fsioLastValue[i]);
2015-01-14 17:06:02 -08:00
// scheduleMsg(logger, "user-defined #%d value=%f", i, engine->engineConfiguration2->fsioLastValue[i]);
2014-12-27 13:03:38 -08:00
showFsio(NULL, fsioLogics[i]);
}
}
for (int i = 0; i < LE_COMMAND_COUNT; i++) {
float v = boardConfiguration->fsio_setting[i];
if (!cisnan(v)) {
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "user property #%d: %f", i + 1, v);
2014-12-27 13:03:38 -08:00
}
}
}
/**
* set_fsio_setting 0 0.11
*/
static void setFsioSetting(float indexF, float value) {
int index = indexF;
if (index < 0 || index >= LE_COMMAND_COUNT) {
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "invalid index %d", index);
2014-12-27 13:03:38 -08:00
return;
}
engineConfiguration->bc.fsio_setting[index] = value;
showFsioInfo();
}
static void setFsioFrequency(int index, int frequency) {
index--;
if (index < 0 || index >= LE_COMMAND_COUNT) {
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "invalid index %d", index);
2014-12-27 13:03:38 -08:00
return;
}
boardConfiguration->fsioFrequency[index] = frequency;
2015-01-15 13:03:51 -08:00
scheduleMsg(logger, "Setting FSIO frequency %d on #%d", frequency,
index + 1);
2014-12-27 13:03:38 -08:00
}
2015-01-15 13:03:51 -08:00
static void setUserOutput(const char *indexStr, const char *quotedLine,
Engine *engine) {
2014-12-27 13:03:38 -08:00
int index = atoi(indexStr) - 1;
if (index < 0 || index >= LE_COMMAND_COUNT) {
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "invalid index %d", index);
2014-12-27 13:03:38 -08:00
return;
}
char * l = unquote((char*) quotedLine);
if (strlen(l) > LE_COMMAND_LENGTH - 1) {
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "Too long %d", strlen(l));
2014-12-27 13:03:38 -08:00
return;
}
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "setting user out #%d to [%s]", index + 1, l);
2014-12-27 13:03:38 -08:00
strcpy(engine->engineConfiguration->bc.le_formulas[index], l);
// this would apply the changes
applyFsioConfiguration(PASS_ENGINE_PARAMETER_F);
showFsioInfo();
}
static void eval(char *line, Engine *engine) {
line = unquote(line);
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "Parsing [%s]", line);
2014-12-27 13:03:38 -08:00
evalPool.reset();
LEElement * e = evalPool.parseExpression(line);
if (e == NULL) {
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "parsing failed");
2014-12-27 13:03:38 -08:00
} else {
float result = evalCalc.getValue2(e, engine);
2015-01-14 17:06:02 -08:00
scheduleMsg(logger, "Eval result: %f", result);
2014-12-27 13:03:38 -08:00
}
}
void runFsio(void) {
for (int i = 0; i < LE_COMMAND_COUNT; i++) {
handleFsio(engine, i);
}
#if EFI_FUEL_PUMP
2015-01-15 13:03:51 -08:00
if (boardConfiguration->fuelPumpPin != GPIO_UNASSIGNED
&& engineConfiguration->isFuelPumpEnabled) {
2015-01-12 20:03:39 -08:00
setPinState("pump", &enginePins.fuelPumpRelay, fuelPumpLogic, engine);
2014-12-27 13:03:38 -08:00
}
#endif
2014-12-29 20:03:34 -08:00
/**
* main relay is always on if ECU is on, that's a good enough initial implementation
*/
if (boardConfiguration->mainRelayPin != GPIO_UNASSIGNED)
2015-01-12 20:03:39 -08:00
enginePins.mainRelay.setValue(true);
enginePins.o2heater.setValue(engine->rpmCalculator.isRunning());
2014-12-27 13:03:38 -08:00
if (boardConfiguration->acRelayPin != GPIO_UNASSIGNED) {
2015-01-12 20:03:39 -08:00
setPinState("A/C", &enginePins.acRelay, acRelayLogic, engine);
2014-12-27 13:03:38 -08:00
}
if (boardConfiguration->alternatorControlPin != GPIO_UNASSIGNED) {
2015-01-15 13:03:51 -08:00
setPinState("alternator", &enginePins.alternatorField, alternatorLogic,
engine);
2014-12-27 13:03:38 -08:00
}
if (boardConfiguration->fanPin != GPIO_UNASSIGNED) {
2015-01-12 20:03:39 -08:00
setPinState("fan", &enginePins.fanRelay, radiatorFanLogic, engine);
2014-12-27 13:03:38 -08:00
}
}
static pin_output_mode_e defa = OM_DEFAULT;
2015-01-14 17:06:02 -08:00
void initFsioImpl(Logging *sharedLogger, Engine *engine) {
logger = sharedLogger;
2014-12-27 13:03:38 -08:00
#if EFI_FUEL_PUMP
fuelPumpLogic = sysPool.parseExpression(FUEL_PUMP_LOGIC);
#endif
acRelayLogic = sysPool.parseExpression(AC_RELAY_LOGIC);
radiatorFanLogic = sysPool.parseExpression(FAN_CONTROL_LOGIC);
alternatorLogic = sysPool.parseExpression(ALTERNATOR_LOGIC);
2014-12-27 14:03:37 -08:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2014-12-27 13:03:38 -08:00
for (int i = 0; i < LE_COMMAND_COUNT; i++) {
brain_pin_e brainPin = boardConfiguration->fsioPins[i];
if (brainPin != GPIO_UNASSIGNED) {
int frequency = boardConfiguration->fsioFrequency[i];
if (frequency == 0) {
2015-01-15 13:03:51 -08:00
outputPinRegisterExt2(getGpioPinName(i), &fsioOutputs[i],
boardConfiguration->fsioPins[i], &defa);
2014-12-27 13:03:38 -08:00
} else {
2015-01-15 13:03:51 -08:00
startSimplePwmExt(&fsioPwm[i], "FSIO", brainPin, &fsioOutputs[i],
frequency, 0.5f, applyPinState);
2014-12-27 13:03:38 -08:00
}
}
}
2015-01-15 13:03:51 -08:00
for (int i = 0; i < LE_COMMAND_COUNT; i++) {
brain_pin_e inputPin = engineConfiguration->fsioInpus[i];
if (inputPin != GPIO_UNASSIGNED) {
}
}
2014-12-27 14:03:37 -08:00
#endif /* EFI_PROD_CODE */
2015-01-15 13:03:51 -08:00
addConsoleActionSSP("set_fsio", (VoidCharPtrCharPtrVoidPtr) setUserOutput,
engine);
2014-12-27 13:03:38 -08:00
addConsoleActionSS("set_fsio_pin", (VoidCharPtrCharPtr) setFsioPin);
addConsoleActionII("set_fsio_frequency", (VoidIntInt) setFsioFrequency);
addConsoleActionFF("set_fsio_setting", setFsioSetting);
addConsoleAction("fsioinfo", showFsioInfo);
addConsoleActionSP("eval", (VoidCharPtrVoidPtr) eval, engine);
}
#endif
#endif /* EFI_FSIO */