diff --git a/firmware/hw_layer/hw_layer.mk b/firmware/hw_layer/hw_layer.mk index 04c70ac206..607d0bd679 100644 --- a/firmware/hw_layer/hw_layer.mk +++ b/firmware/hw_layer/hw_layer.mk @@ -24,6 +24,8 @@ HW_LAYER_EMS_CPP = $(HW_LAYER_EGT_CPP) \ $(PROJECT_DIR)/hw_layer/adc_subscription.cpp \ $(PROJECT_DIR)/hw_layer/pwm_generator.cpp \ $(PROJECT_DIR)/hw_layer/trigger_input.cpp \ + $(PROJECT_DIR)/hw_layer/trigger_input_icu.cpp \ + $(PROJECT_DIR)/hw_layer/trigger_input_exti.cpp \ $(PROJECT_DIR)/hw_layer/hip9011.cpp \ $(PROJECT_DIR)/hw_layer/mc33816.cpp \ $(PROJECT_DIR)/hw_layer/hip9011_logic.cpp \ diff --git a/firmware/hw_layer/trigger_input.cpp b/firmware/hw_layer/trigger_input.cpp index a616c01522..dba4479d1b 100644 --- a/firmware/hw_layer/trigger_input.cpp +++ b/firmware/hw_layer/trigger_input.cpp @@ -1,290 +1,14 @@ -/** +/* * @file trigger_input.cpp - * @brief Position sensor hardware layer (ICU and PAL drivers) * - * todo: code reuse with digital_input_hw.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_hw.cp - * - * @date Dec 30, 2012 - * @author Andrey Belomutskiy, (c) 2012-2018 + * @date Nov 11, 2019 + * @author Andrey Belomutskiy, (c) 2012-2019 */ #include "global.h" - -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) - #include "trigger_input.h" -#include "digital_input_hw.h" -#include "digital_input_exti.h" -#include "pin_repository.h" -#include "trigger_structure.h" -#include "trigger_central.h" -#include "engine_configuration.h" -#define TRIGGER_SUPPORTED_CHANNELS 2 - -extern bool hasFirmwareErrorFlag; - -EXTERN_ENGINE -; -static Logging *logger; - -#if EFI_PROD_CODE -/* PAL based implementation */ -#if (HAL_TRIGGER_USE_PAL == TRUE) && (PAL_USE_CALLBACKS == TRUE) - -/* static variables for PAL implementation */ -static ioline_t primary_line; - -static void shaft_callback(void *arg) { - ioline_t pal_line = (ioline_t)arg; - // todo: support for 3rd trigger input channel - // todo: start using real event time from HW event, not just software timer? - if (hasFirmwareErrorFlag) - return; - - bool isPrimary = pal_line == primary_line; - if (!isPrimary && !TRIGGER_SHAPE(needSecondTriggerInput)) { - return; - } - - bool rise = (palReadLine(pal_line) == PAL_HIGH); - trigger_event_e signal; - // 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) { - ioline_t pal_line = (ioline_t)arg; - - bool rise = (palReadLine(pal_line) == PAL_HIGH); - - if (rise) { - hwHandleVvtCamSignal(TV_RISE); - } else { - hwHandleVvtCamSignal(TV_FALL); - } -} - -static int turnOnTriggerInputPin(const char *msg, brain_pin_e brainPin, bool is_shaft) { - 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 */ - 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); -} - -static void turnOffTriggerInputPin(brain_pin_e brainPin) { - efiExtiDisablePin(brainPin); -} - -static void setPrimaryChannel(brain_pin_e brainPin) { - 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; - -static void cam_icu_width_callback(ICUDriver *icup) { - (void)icup; - hwHandleVvtCamSignal(TV_RISE); -} - -static void cam_icu_period_callback(ICUDriver *icup) { - (void)icup; - hwHandleVvtCamSignal(TV_FALL); -} - -/** - * 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++; -// todo: support for 3rd trigger input channel -// todo: start using real event time from HW event, not just software timer? - if (hasFirmwareErrorFlag) - return; - int isPrimary = icup == primaryCrankDriver; - 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); -} - -static void shaft_icu_period_callback(ICUDriver *icup) { - if (!hwTriggerInputEnabled) { - return; - } - icuWidthPeriodCounter++; - if (hasFirmwareErrorFlag) - return; - int isPrimary = icup == primaryCrankDriver; - 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); -} - -/** - * 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}; - -static int turnOnTriggerInputPin(const char *msg, brain_pin_e brainPin, bool is_shaft) { - ICUConfig *icucfg; - - if (brainPin == GPIO_UNASSIGNED) { - return -1; - } - - if (is_shaft) { - icucfg = &shaft_icucfg; - } else { - 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)); - } - } - return 0; -} - -static void turnOffTriggerInputPin(brain_pin_e brainPin) { - ICUDriver *driver = getInputCaptureDriver("trigger_off", brainPin); - if (driver != NULL) { - icuDisableNotifications(driver); - icuStopCapture(driver); - icuStop(driver); - scheduleMsg(logger, "turnOffTriggerInputPin %s", hwPortname(brainPin)); - turnOffCapturePin(brainPin); - } -} - -static void setPrimaryChannel(brain_pin_e brainPin) { - primaryCrankDriver = getInputCaptureDriver("primary", brainPin); -} - -#endif /* HAL_USE_ICU */ -#endif /* EFI_PROD_CODE */ - -/*==========================================================================*/ -/* Exported functions. */ -/*==========================================================================*/ - -void turnOnTriggerInputPins(Logging *sharedLogger) { - logger = sharedLogger; - - applyNewTriggerInputPins(); -} - -void stopTriggerInputPins(void) { -#if EFI_PROD_CODE - for (int i = 0; i < TRIGGER_SUPPORTED_CHANNELS; i++) { - if (isConfigurationChanged(bc.triggerInputPins[i])) { - turnOffTriggerInputPin(activeConfiguration.bc.triggerInputPins[i]); - } - } - for (int i = 0; i < CAM_INPUTS_COUNT; i++) { - if (isConfigurationChanged(camInputs[i])) { - turnOffTriggerInputPin(activeConfiguration.camInputs[i]); - } - } -#endif /* EFI_PROD_CODE */ -} - -void startTriggerInputPins(void) { -#if EFI_PROD_CODE - for (int i = 0; i < TRIGGER_SUPPORTED_CHANNELS; i++) { - if (isConfigurationChanged(bc.triggerInputPins[i])) { - const char * msg = (i == 0 ? "trigger#1" : (i == 1 ? "trigger#2" : "trigger#3")); - turnOnTriggerInputPin(msg, CONFIGB(triggerInputPins)[i], true); - } - } - - for (int i = 0; i < CAM_INPUTS_COUNT; i++) { - if (isConfigurationChanged(camInputs[i])) { - turnOnTriggerInputPin("cam", engineConfiguration->camInputs[i], false); - } - } - - setPrimaryChannel(CONFIGB(triggerInputPins)[0]); -#endif /* EFI_PROD_CODE */ -} +#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__) void applyNewTriggerInputPins(void) { // first we will turn off all the changed pins @@ -293,4 +17,4 @@ void applyNewTriggerInputPins(void) { startTriggerInputPins(); } -#endif /* (EFI_SHAFT_POSITION_INPUT && (HAL_TRIGGER_USE_PAL == TRUE || HAL_USE_ICU == TRUE) && (HAL_USE_COMP == FALSE)) */ +#endif /* EFI_SHAFT_POSITION_INPUT */ diff --git a/firmware/hw_layer/trigger_input.h b/firmware/hw_layer/trigger_input.h index b48c1162ba..aacdcd6132 100644 --- a/firmware/hw_layer/trigger_input.h +++ b/firmware/hw_layer/trigger_input.h @@ -11,6 +11,8 @@ #include "engine.h" +#define TRIGGER_SUPPORTED_CHANNELS 2 + void turnOnTriggerInputPins(Logging *sharedLogger); void applyNewTriggerInputPins(void); void startTriggerInputPins(void); diff --git a/firmware/hw_layer/trigger_input_comp.cpp b/firmware/hw_layer/trigger_input_comp.cpp index b1f7bf498c..048f528829 100644 --- a/firmware/hw_layer/trigger_input_comp.cpp +++ b/firmware/hw_layer/trigger_input_comp.cpp @@ -20,8 +20,6 @@ #include "trigger_central.h" #include "engine_configuration.h" -#define TRIGGER_SUPPORTED_CHANNELS 2 - extern bool hasFirmwareErrorFlag; EXTERN_ENGINE @@ -119,11 +117,4 @@ void stopTriggerInputPins(void) { #endif } -void applyNewTriggerInputPins(void) { - // first we will turn off all the changed pins - stopTriggerInputPins(); - // then we will enable all the changed pins - startTriggerInputPins(); -} - #endif /* EFI_SHAFT_POSITION_INPUT && HAL_USE_COMP */ diff --git a/firmware/hw_layer/trigger_input_exti.cpp b/firmware/hw_layer/trigger_input_exti.cpp new file mode 100644 index 0000000000..521fa61a52 --- /dev/null +++ b/firmware/hw_layer/trigger_input_exti.cpp @@ -0,0 +1,17 @@ +/** + * @file trigger_input_exti.cpp + * @brief Position sensor hardware layer - PAL version + * + * todo: VVT implementation is a nasty copy-paste :( + * + * see digital_input_hw.cp + * + * @date Dec 30, 2012 + * @author Andrey Belomutskiy, (c) 2012-2019 + */ + +#include "global.h" + +#if EFI_SHAFT_POSITION_INPUT && (HAL_TRIGGER_USE_PAL == TRUE) && (HAL_USE_COMP == FALSE) + +#endif /* (EFI_SHAFT_POSITION_INPUT && (HAL_TRIGGER_USE_PAL == TRUE) && (HAL_USE_COMP == FALSE)) */