rusefi-1/firmware/hw_layer/trigger_input_icu.cpp

175 lines
5.8 KiB
C++
Raw Normal View History

2019-11-11 18:26:09 -08:00
/**
* @file trigger_input_icu.cpp
2019-11-11 19:19:35 -08:00
* @brief Position sensor hardware layer - ICU version
2019-11-11 18:26:09 -08:00
*
* todo: code reuse with digital_input_icu.cpp was never finished
2019-11-11 18:26:09 -08:00
* todo: at the moment due to half-done code reuse we already depend on EFI_ICU_INPUTS but still have custom code
* todo: VVT implementation is a nasty copy-paste :(
*
* see digital_input_icu.cpp
2019-11-11 18:26:09 -08:00
*
* @date Dec 30, 2012
* @author Andrey Belomutskiy, (c) 2012-2019
*/
#include "global.h"
volatile int icuWidthCallbackCounter = 0;
volatile int icuWidthPeriodCounter = 0;
2019-11-11 19:19:35 -08:00
#if EFI_SHAFT_POSITION_INPUT && (HAL_USE_ICU == TRUE) && (HAL_USE_COMP == FALSE)
2019-11-11 18:26:09 -08:00
#include "trigger_input.h"
#include "digital_input_icu.h"
2019-11-11 19:19:35 -08:00
EXTERN_ENGINE;
2019-11-11 18:26:09 -08:00
extern bool hasFirmwareErrorFlag;
static Logging *logger;
2019-11-12 18:05:51 -08:00
static ICUDriver *primaryCrankDriver;
static void cam_icu_width_callback(ICUDriver *icup) {
(void)icup;
2019-11-11 18:26:09 -08:00
hwHandleVvtCamSignal(TV_RISE);
}
2019-11-12 18:05:51 -08:00
static void cam_icu_period_callback(ICUDriver *icup) {
(void)icup;
2019-11-11 18:26:09 -08:00
hwHandleVvtCamSignal(TV_FALL);
}
/**
* that's hardware timer input capture IRQ entry point
* 'width' events happens before the 'period' event
*/
2019-11-12 18:05:51 -08:00
static void shaft_icu_width_callback(ICUDriver *icup) {
2019-11-11 19:19:35 -08:00
if (!engine->hwTriggerInputEnabled) {
2019-11-11 18:26:09 -08:00
return;
}
icuWidthCallbackCounter++;
// todo: support for 3rd trigger input channel
// todo: start using real event time from HW event, not just software timer?
if (hasFirmwareErrorFlag)
return;
2019-11-12 18:05:51 -08:00
int isPrimary = icup == primaryCrankDriver;
2019-11-11 18:26:09 -08:00
if (!isPrimary && !TRIGGER_SHAPE(needSecondTriggerInput)) {
return;
}
// icucnt_t last_width = icuGetWidth(icup); so far we are fine with system time
// todo: add support for 3rd channel
trigger_event_e signal = isPrimary ? (engineConfiguration->invertPrimaryTriggerSignal ? SHAFT_PRIMARY_FALLING : SHAFT_PRIMARY_RISING) : (engineConfiguration->invertSecondaryTriggerSignal ? SHAFT_SECONDARY_FALLING : SHAFT_SECONDARY_RISING);
hwHandleShaftSignal(signal);
}
2019-11-12 18:05:51 -08:00
static void shaft_icu_period_callback(ICUDriver *icup) {
2019-11-11 19:19:35 -08:00
if (!engine->hwTriggerInputEnabled) {
2019-11-11 18:26:09 -08:00
return;
}
icuWidthPeriodCounter++;
if (hasFirmwareErrorFlag)
return;
2019-11-12 18:05:51 -08:00
int isPrimary = icup == primaryCrankDriver;
2019-11-11 18:26:09 -08:00
if (!isPrimary && !TRIGGER_SHAPE(needSecondTriggerInput)) {
return;
}
// todo: add support for 3rd channel
// icucnt_t last_period = icuGetPeriod(icup); so far we are fine with system time
trigger_event_e signal =
isPrimary ? (engineConfiguration->invertPrimaryTriggerSignal ? SHAFT_PRIMARY_RISING : SHAFT_PRIMARY_FALLING) : (engineConfiguration->invertSecondaryTriggerSignal ? SHAFT_SECONDARY_RISING : SHAFT_SECONDARY_FALLING);
hwHandleShaftSignal(signal);
}
2019-11-12 18:05:51 -08:00
/**
* the main purpose of this configuration structure is to specify the input interrupt callbacks
*/
static ICUConfig shaft_icucfg = { ICU_INPUT_ACTIVE_LOW,
100000, /* 100kHz ICU clock frequency. */
shaft_icu_width_callback,
shaft_icu_period_callback,
NULL,
ICU_CHANNEL_1,
0};
/**
* this is about VTTi and stuff kind of cam sensor
*/
static ICUConfig cam_icucfg = { ICU_INPUT_ACTIVE_LOW,
100000, /* 100kHz ICU clock frequency. */
cam_icu_width_callback,
cam_icu_period_callback,
NULL,
ICU_CHANNEL_1,
0};
int turnOnTriggerInputPin(const char *msg, brain_pin_e brainPin, bool isVvtShaft) {
ICUConfig *icucfg;
2019-11-11 18:26:09 -08:00
if (brainPin == GPIO_UNASSIGNED) {
2019-11-12 18:05:51 -08:00
return -1;
2019-11-11 18:26:09 -08:00
}
2019-11-12 18:05:51 -08:00
if (isVvtShaft) {
icucfg = &shaft_icucfg;
} else {
2019-11-12 18:05:51 -08:00
icucfg = &cam_icucfg;
}
// configure pin
turnOnCapturePin(msg, brainPin);
icucfg->channel = getInputCaptureChannel(brainPin);
ICUDriver *driver = getInputCaptureDriver(msg, brainPin);
scheduleMsg(logger, "turnOnTriggerInputPin %s", hwPortname(brainPin));
// todo: reuse 'setWaveReaderMode' method here?
if (driver != NULL) {
// todo: once http://forum.chibios.org/phpbb/viewtopic.php?f=16&t=1757 is fixed
// bool needWidthCallback = !CONFIG(useOnlyRisingEdgeForTrigger) || TRIGGER_SHAPE(useRiseEdge);
// shaft_icucfg.width_cb = needWidthCallback ? shaft_icu_width_callback : NULL;
// bool needPeriodCallback = !CONFIG(useOnlyRisingEdgeForTrigger) || !TRIGGER_SHAPE(useRiseEdge);
// shaft_icucfg.period_cb = needPeriodCallback ? shaft_icu_period_callback : NULL;
efiIcuStart(msg, driver, icucfg);
if (driver->state == ICU_READY) {
efiAssert(CUSTOM_ERR_ASSERT, driver != NULL, "ti: driver is NULL", -1);
efiAssert(CUSTOM_ERR_ASSERT, driver->state == ICU_READY, "ti: driver not ready", -1);
icuStartCapture(driver); // this would change state from READY to WAITING
icuEnableNotifications(driver);
} else {
// we would be here for example if same pin is used for multiple input capture purposes
firmwareError(CUSTOM_ERR_ICU_STATE, "ICU unexpected state [%s]", hwPortname(brainPin));
}
2019-11-11 18:26:09 -08:00
}
2019-11-12 18:05:51 -08:00
return 0;
2019-11-11 18:26:09 -08:00
}
2019-11-11 19:19:35 -08:00
void turnOffTriggerInputPin(brain_pin_e brainPin) {
2019-11-12 18:05:51 -08:00
ICUDriver *driver = getInputCaptureDriver("trigger_off", brainPin);
if (driver != NULL) {
icuDisableNotifications(driver);
icuStopCapture(driver);
icuStop(driver);
scheduleMsg(logger, "turnOffTriggerInputPin %s", hwPortname(brainPin));
turnOffCapturePin(brainPin);
}
2019-11-11 18:26:09 -08:00
}
2019-11-11 19:19:35 -08:00
void setPrimaryChannel(brain_pin_e brainPin) {
2019-11-12 18:05:51 -08:00
primaryCrankDriver = getInputCaptureDriver("primary", brainPin);
2019-11-11 18:26:09 -08:00
}
/*==========================================================================*/
/* Exported functions. */
/*==========================================================================*/
void turnOnTriggerInputPins(Logging *sharedLogger) {
logger = sharedLogger;
applyNewTriggerInputPins();
}
2019-11-11 19:19:35 -08:00
#endif /* (EFI_SHAFT_POSITION_INPUT && (HAL_USE_ICU == TRUE) && (HAL_USE_COMP == FALSE)) */