rusefi-1/firmware/hw_layer/trigger_input.cpp

308 lines
9.9 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
2019-04-12 05:05:53 -07:00
* @file trigger_input.cpp
* @brief Position sensor hardware layer (ICU and PAL drivers)
2015-07-10 06:01:56 -07:00
*
2018-12-12 20:36:36 -08:00
* todo: code reuse with digital_input_hw.cpp was never finished
2018-12-15 22:13:44 -08:00
* todo: at the moment due to half-done code reuse we already depend on EFI_ICU_INPUTS but still have custom code
2018-12-12 20:36:36 -08:00
* todo: VVT implementation is a nasty copy-paste :(
*
* see digital_input_hw.cp
*
2015-07-10 06:01:56 -07:00
* @date Dec 30, 2012
2018-01-20 17:55:31 -08:00
* @author Andrey Belomutskiy, (c) 2012-2018
2015-07-10 06:01:56 -07:00
*/
2018-09-16 19:26:57 -07:00
#include "global.h"
2015-07-10 06:01:56 -07:00
#ifndef HAL_TRIGGER_USE_PAL
#define HAL_TRIGGER_USE_PAL FALSE
#endif /* HAL_TRIGGER_USE_PAL */
volatile int icuWidthCallbackCounter = 0;
volatile int icuWidthPeriodCounter = 0;
bool hwTriggerInputEnabled = true; // this is useful at least for real hardware integration testing
#if EFI_SHAFT_POSITION_INPUT && (HAL_TRIGGER_USE_PAL == TRUE || HAL_USE_ICU == TRUE) && (HAL_USE_COMP == FALSE)
2015-07-10 06:01:56 -07:00
#include "trigger_input.h"
#include "digital_input_hw.h"
#include "digital_input_exti.h"
2015-07-10 06:01:56 -07:00
#include "pin_repository.h"
#include "trigger_structure.h"
#include "trigger_central.h"
#include "engine_configuration.h"
#define TRIGGER_SUPPORTED_CHANNELS 2
2016-01-24 15:01:56 -08:00
extern bool hasFirmwareErrorFlag;
2015-07-10 06:01:56 -07:00
EXTERN_ENGINE
;
static Logging *logger;
2016-09-17 08:03:00 -07:00
int vvtEventRiseCounter = 0;
int vvtEventFallCounter = 0;
#if EFI_PROD_CODE
2019-04-12 05:05:53 -07:00
/* PAL based implementation */
#if (HAL_TRIGGER_USE_PAL == TRUE) && (PAL_USE_CALLBACKS == TRUE)
2019-04-12 05:05:53 -07:00
2019-07-12 18:13:24 -07:00
/* static variables for PAL implementation */
2019-04-12 05:05:53 -07:00
static ioline_t primary_line;
static void shaft_callback(void *arg) {
2019-07-12 18:13:24 -07:00
ioline_t pal_line = (ioline_t)arg;
2019-04-12 05:05:53 -07:00
// todo: support for 3rd trigger input channel
// todo: start using real event time from HW event, not just software timer?
if (hasFirmwareErrorFlag)
return;
2019-07-12 18:13:24 -07:00
bool isPrimary = pal_line == primary_line;
2019-04-12 05:05:53 -07:00
if (!isPrimary && !TRIGGER_SHAPE(needSecondTriggerInput)) {
return;
}
2019-07-12 18:13:24 -07:00
bool rise = (palReadLine(pal_line) == PAL_HIGH);
trigger_event_e signal;
2019-04-12 05:05:53 -07:00
// todo: add support for 3rd channel
if (rise) {
signal = isPrimary ?
(engineConfiguration->invertPrimaryTriggerSignal ? SHAFT_PRIMARY_FALLING : SHAFT_PRIMARY_RISING) :
(engineConfiguration->invertSecondaryTriggerSignal ? SHAFT_SECONDARY_FALLING : SHAFT_SECONDARY_RISING);
} else {
signal = isPrimary ?
(engineConfiguration->invertPrimaryTriggerSignal ? SHAFT_PRIMARY_RISING : SHAFT_PRIMARY_FALLING) :
(engineConfiguration->invertSecondaryTriggerSignal ? SHAFT_SECONDARY_RISING : SHAFT_SECONDARY_FALLING);
}
hwHandleShaftSignal(signal);
}
static void cam_callback(void *arg) {
2019-04-12 05:05:53 -07:00
ioline_t pal_line = (ioline_t)arg;
2019-07-12 18:13:24 -07:00
bool rise = (palReadLine(pal_line) == PAL_HIGH);
2019-04-12 05:05:53 -07:00
if (rise) {
vvtEventRiseCounter++;
hwHandleVvtCamSignal(TV_RISE);
} else {
vvtEventFallCounter++;
hwHandleVvtCamSignal(TV_FALL);
}
}
static int turnOnTriggerInputPin(const char *msg, brain_pin_e brainPin, bool is_shaft) {
2019-04-12 05:05:53 -07:00
scheduleMsg(logger, "turnOnTriggerInputPin(PAL) %s %s", msg, hwPortname(brainPin));
/* TODO:
* * do not set to both edges if we need only one
* * simplify callback in case of one edge */
2019-07-12 18:13:24 -07:00
ioline_t pal_line = PAL_LINE(getHwPort("trg", brainPin), getHwPin("trg", brainPin));
return efiExtiEnablePin(msg, brainPin, PAL_EVENT_MODE_BOTH_EDGES, is_shaft ? shaft_callback : cam_callback, (void *)pal_line);
2019-04-12 05:05:53 -07:00
}
static void turnOffTriggerInputPin(brain_pin_e brainPin) {
efiExtiDisablePin(brainPin);
2019-04-12 05:05:53 -07:00
}
static void setPrimaryChannel(brain_pin_e brainPin) {
2019-04-12 05:05:53 -07:00
primary_line = PAL_LINE(getHwPort("trg", brainPin), getHwPin("trg", brainPin));
}
/* ICU based implementation */
#elif (HAL_USE_ICU)
/* static vars for ICU implementation */
static ICUDriver *primaryCrankDriver;
2016-08-20 06:02:06 -07:00
static void cam_icu_width_callback(ICUDriver *icup) {
2017-03-22 16:46:05 -07:00
(void)icup;
2016-09-17 08:03:00 -07:00
vvtEventRiseCounter++;
2016-08-20 20:02:09 -07:00
hwHandleVvtCamSignal(TV_RISE);
2016-08-20 06:02:06 -07:00
}
static void cam_icu_period_callback(ICUDriver *icup) {
2017-03-22 16:46:05 -07:00
(void)icup;
2016-09-17 08:03:00 -07:00
vvtEventFallCounter++;
2016-08-20 20:02:09 -07:00
hwHandleVvtCamSignal(TV_FALL);
2016-08-20 06:02:06 -07:00
}
2015-07-10 06:01:56 -07:00
/**
* that's hardware timer input capture IRQ entry point
* 'width' events happens before the 'period' event
*/
static void shaft_icu_width_callback(ICUDriver *icup) {
if (!hwTriggerInputEnabled) {
return;
}
icuWidthCallbackCounter++;
2015-07-10 06:01:56 -07:00
// todo: support for 3rd trigger input channel
// todo: start using real event time from HW event, not just software timer?
2016-01-24 15:01:56 -08:00
if (hasFirmwareErrorFlag)
return;
2015-07-10 06:01:56 -07:00
int isPrimary = icup == primaryCrankDriver;
2017-10-16 11:31:02 -07:00
if (!isPrimary && !TRIGGER_SHAPE(needSecondTriggerInput)) {
2015-07-10 06:01:56 -07:00
return;
}
// icucnt_t last_width = icuGetWidth(icup); so far we are fine with system time
// todo: add support for 3rd channel
2017-10-16 12:07:36 -07:00
trigger_event_e signal = isPrimary ? (engineConfiguration->invertPrimaryTriggerSignal ? SHAFT_PRIMARY_FALLING : SHAFT_PRIMARY_RISING) : (engineConfiguration->invertSecondaryTriggerSignal ? SHAFT_SECONDARY_FALLING : SHAFT_SECONDARY_RISING);
2015-07-10 06:01:56 -07:00
hwHandleShaftSignal(signal);
}
static void shaft_icu_period_callback(ICUDriver *icup) {
if (!hwTriggerInputEnabled) {
return;
}
icuWidthPeriodCounter++;
2016-01-24 15:01:56 -08:00
if (hasFirmwareErrorFlag)
return;
2015-07-10 06:01:56 -07:00
int isPrimary = icup == primaryCrankDriver;
2017-10-16 11:31:02 -07:00
if (!isPrimary && !TRIGGER_SHAPE(needSecondTriggerInput)) {
2015-07-10 06:01:56 -07:00
return;
}
// todo: add support for 3rd channel
// icucnt_t last_period = icuGetPeriod(icup); so far we are fine with system time
2015-08-22 08:02:10 -07:00
trigger_event_e signal =
2017-10-16 12:07:36 -07:00
isPrimary ? (engineConfiguration->invertPrimaryTriggerSignal ? SHAFT_PRIMARY_RISING : SHAFT_PRIMARY_FALLING) : (engineConfiguration->invertSecondaryTriggerSignal ? SHAFT_SECONDARY_RISING : SHAFT_SECONDARY_FALLING);
2015-07-10 06:01:56 -07:00
hwHandleShaftSignal(signal);
}
/**
* the main purpose of this configuration structure is to specify the input interrupt callbacks
*/
2017-03-22 16:46:05 -07:00
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};
2015-07-10 06:01:56 -07:00
2016-08-20 06:02:06 -07:00
/**
* this is about VTTi and stuff kind of cam sensor
*/
2017-03-22 16:46:05 -07:00
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};
2016-08-20 06:02:06 -07:00
2019-04-12 05:05:53 -07:00
static int turnOnTriggerInputPin(const char *msg, brain_pin_e brainPin, bool is_shaft) {
ICUConfig *icucfg;
if (brainPin == GPIO_UNASSIGNED)
return -1;
2016-08-20 06:02:06 -07:00
2019-04-12 05:05:53 -07:00
if (is_shaft)
icucfg = &shaft_icucfg;
else
icucfg = &cam_icucfg;
2016-08-20 20:02:09 -07:00
2015-07-10 06:01:56 -07:00
// configure pin
2019-04-12 05:05:53 -07:00
turnOnCapturePin(msg, brainPin);
icucfg->channel = getInputCaptureChannel(brainPin);
2015-07-10 06:01:56 -07:00
2019-04-12 05:05:53 -07:00
ICUDriver *driver = getInputCaptureDriver(msg, brainPin);
scheduleMsg(logger, "turnOnTriggerInputPin %s", hwPortname(brainPin));
2015-07-10 06:01:56 -07:00
// todo: reuse 'setWaveReaderMode' method here?
if (driver != NULL) {
// todo: once http://forum.chibios.org/phpbb/viewtopic.php?f=16&t=1757 is fixed
2016-02-27 20:03:34 -08:00
// bool needWidthCallback = !CONFIG(useOnlyRisingEdgeForTrigger) || TRIGGER_SHAPE(useRiseEdge);
2015-07-10 06:01:56 -07:00
// shaft_icucfg.width_cb = needWidthCallback ? shaft_icu_width_callback : NULL;
2016-02-27 20:03:34 -08:00
// bool needPeriodCallback = !CONFIG(useOnlyRisingEdgeForTrigger) || !TRIGGER_SHAPE(useRiseEdge);
2015-07-10 06:01:56 -07:00
// shaft_icucfg.period_cb = needPeriodCallback ? shaft_icu_period_callback : NULL;
2019-04-07 15:25:46 -07:00
efiIcuStart(msg, driver, icucfg);
2015-07-10 06:01:56 -07:00
if (driver->state == ICU_READY) {
2019-04-20 10:42:31 -07:00
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
2017-03-22 16:46:05 -07:00
icuEnableNotifications(driver);
2015-07-10 06:01:56 -07:00
} else {
// we would be here for example if same pin is used for multiple input capture purposes
2019-04-12 05:05:53 -07:00
firmwareError(CUSTOM_ERR_ICU_STATE, "ICU unexpected state [%s]", hwPortname(brainPin));
2015-07-10 06:01:56 -07:00
}
}
2019-04-12 05:05:53 -07:00
return 0;
2015-07-10 06:01:56 -07:00
}
2019-04-12 05:05:53 -07:00
static void turnOffTriggerInputPin(brain_pin_e brainPin) {
ICUDriver *driver = getInputCaptureDriver("trigger_off", brainPin);
2015-07-10 06:01:56 -07:00
if (driver != NULL) {
2017-03-22 16:46:05 -07:00
icuDisableNotifications(driver);
2017-03-22 16:16:45 -07:00
icuStopCapture(driver);
2015-07-10 06:01:56 -07:00
icuStop(driver);
2019-04-12 05:05:53 -07:00
scheduleMsg(logger, "turnOffTriggerInputPin %s", hwPortname(brainPin));
turnOffCapturePin(brainPin);
2015-07-10 06:01:56 -07:00
}
}
2019-04-12 05:05:53 -07:00
static void setPrimaryChannel(brain_pin_e brainPin) {
primaryCrankDriver = getInputCaptureDriver("primary", brainPin);
2015-07-10 06:01:56 -07:00
}
2019-04-12 05:05:53 -07:00
#endif /* HAL_USE_ICU */
#endif /* EFI_PROD_CODE */
2019-04-12 05:05:53 -07:00
/*==========================================================================*/
/* Exported functions. */
/*==========================================================================*/
2015-07-10 06:01:56 -07:00
void turnOnTriggerInputPins(Logging *sharedLogger) {
logger = sharedLogger;
2016-08-20 20:02:09 -07:00
applyNewTriggerInputPins();
2015-07-10 06:01:56 -07:00
}
void stopTriggerInputPins(void) {
2019-04-12 05:33:40 -07:00
#if EFI_PROD_CODE
2015-08-22 08:02:10 -07:00
for (int i = 0; i < TRIGGER_SUPPORTED_CHANNELS; i++) {
if (CONFIGB(triggerInputPins)[i]
2015-08-22 08:02:10 -07:00
!= activeConfiguration.bc.triggerInputPins[i]) {
turnOffTriggerInputPin(activeConfiguration.bc.triggerInputPins[i]);
}
2015-07-10 06:01:56 -07:00
}
2019-07-12 18:13:24 -07:00
for (int i = 0; i < CAM_INPUTS_COUNT; i++) {
if (engineConfiguration->camInputs[i] != activeConfiguration.camInputs[i]) {
turnOffTriggerInputPin(activeConfiguration.camInputs[i]);
}
2016-09-17 10:02:39 -07:00
}
2019-04-12 05:33:40 -07:00
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
}
void startTriggerInputPins(void) {
2019-04-12 05:33:40 -07:00
#if EFI_PROD_CODE
2015-08-22 08:02:10 -07:00
for (int i = 0; i < TRIGGER_SUPPORTED_CHANNELS; i++) {
if (CONFIGB(triggerInputPins)[i]
2015-08-22 08:02:10 -07:00
!= activeConfiguration.bc.triggerInputPins[i]) {
2016-12-27 09:00:48 -08:00
const char * msg = (i == 0 ? "trigger#1" : (i == 1 ? "trigger#2" : "trigger#3"));
2019-04-12 05:05:53 -07:00
turnOnTriggerInputPin(msg, CONFIGB(triggerInputPins)[i], true);
2015-08-22 08:02:10 -07:00
}
2015-07-10 06:01:56 -07:00
}
2019-07-12 18:13:24 -07:00
for (int i = 0; i < CAM_INPUTS_COUNT; i++) {
if (engineConfiguration->camInputs[i] != activeConfiguration.camInputs[i]) {
turnOnTriggerInputPin("cam", engineConfiguration->camInputs[i], false);
}
2016-08-20 20:02:09 -07:00
}
2016-08-20 16:02:07 -07:00
2019-04-12 05:05:53 -07:00
setPrimaryChannel(CONFIGB(triggerInputPins)[0]);
2019-04-12 05:33:40 -07:00
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
}
void applyNewTriggerInputPins(void) {
2019-04-12 05:05:53 -07:00
// first we will turn off all the changed pins
stopTriggerInputPins();
2019-04-12 05:05:53 -07:00
// then we will enable all the changed pins
startTriggerInputPins();
}
#endif /* (EFI_SHAFT_POSITION_INPUT && (HAL_TRIGGER_USE_PAL == TRUE || HAL_USE_ICU == TRUE) && (HAL_USE_COMP == FALSE)) */