rusefi-1/firmware/hw_layer/trigger_input_icu.cpp

126 lines
3.7 KiB
C++

/**
* @file trigger_input_icu.cpp
* @brief Position sensor hardware layer - ICU version
*
* todo: code reuse with digital_input_icu.cpp was never finished
* 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
*
* @date Dec 30, 2012
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "global.h"
volatile int icuWidthCallbackCounter = 0;
volatile int icuWidthPeriodCounter = 0;
#if EFI_SHAFT_POSITION_INPUT && (HAL_USE_ICU == TRUE)
#include "trigger_input.h"
#include "digital_input_icu.h"
EXTERN_ENGINE;
extern bool hasFirmwareErrorFlag;
static Logging *logger;
static void vvtWidthCallback(void *) {
hwHandleVvtCamSignal(TV_RISE, getTimeNowNt());
}
static void vvtPeriodCallback(void *) {
hwHandleVvtCamSignal(TV_FALL, getTimeNowNt());
}
/**
* that's hardware timer input capture IRQ entry point
* 'width' events happens before the 'period' event
*/
static void shaftWidthCallback(bool isPrimary) {
efitick_t stamp = getTimeNowNt();
if (!engine->hwTriggerInputEnabled) {
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;
if (!isPrimary && !TRIGGER_WAVEFORM(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, stamp);
}
static void shaftPeriodCallback(bool isPrimary) {
efitick_t stamp = getTimeNowNt();
if (!engine->hwTriggerInputEnabled) {
return;
}
icuWidthPeriodCounter++;
if (hasFirmwareErrorFlag)
return;
if (!isPrimary && !TRIGGER_WAVEFORM(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, stamp);
}
/*==========================================================================*/
/* Exported functions. */
/*==========================================================================*/
int icuTriggerTurnOnInputPin(const char *msg, int index, bool isTriggerShaft) {
(void)msg;
brain_pin_e brainPin = isTriggerShaft ? CONFIG(triggerInputPins)[index] : engineConfiguration->camInputs[index];
if (brainPin == GPIO_UNASSIGNED) {
return -1;
}
digital_input_s* input = startDigitalCapture("trigger", brainPin, true);
if (input == NULL) {
/* error already reported */
return -1;
}
if (isTriggerShaft) {
void * arg = (void*) (index == 0);
input->setWidthCallback((VoidInt)(void*)shaftWidthCallback, arg);
input->setPeriodCallback((VoidInt)(void*)shaftPeriodCallback, arg);
} else {
input->setWidthCallback((VoidInt)(void*)vvtWidthCallback, NULL);
input->setPeriodCallback((VoidInt)(void*)vvtPeriodCallback, NULL);
}
return 0;
}
void icuTriggerTurnOffInputPin(brain_pin_e brainPin) {
stopDigitalCapture("trigger", brainPin);
}
void icuTriggerSetPrimaryChannel(brain_pin_e brainPin) {
(void)brainPin;
}
void icuTriggerTurnOnInputPins(Logging *sharedLogger) {
logger = sharedLogger;
}
#endif /* (EFI_SHAFT_POSITION_INPUT && (HAL_USE_ICU == TRUE)) */