diff --git a/firmware/hw_layer/trigger_input.cpp b/firmware/hw_layer/trigger_input.cpp index 3bf42ff9e2..ec10a36a03 100644 --- a/firmware/hw_layer/trigger_input.cpp +++ b/firmware/hw_layer/trigger_input.cpp @@ -30,13 +30,13 @@ void startTriggerInputPins(void) { 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, i, true); + turnOnTriggerInputPin(msg, CONFIGB(triggerInputPins)[i], true); } } for (int i = 0; i < CAM_INPUTS_COUNT; i++) { if (isConfigurationChanged(camInputs[i])) { - turnOnTriggerInputPin("cam", i, false); + turnOnTriggerInputPin("cam", engineConfiguration->camInputs[i], false); } } diff --git a/firmware/hw_layer/trigger_input.h b/firmware/hw_layer/trigger_input.h index c6094f61c7..cf7c44422c 100644 --- a/firmware/hw_layer/trigger_input.h +++ b/firmware/hw_layer/trigger_input.h @@ -22,6 +22,6 @@ void startTriggerInputPins(void); void stopTriggerInputPins(void); void setPrimaryChannel(brain_pin_e brainPin); void turnOffTriggerInputPin(brain_pin_e brainPin); -void turnOnTriggerInputPin(const char *msg, int index, bool isTriggerShaft); +int turnOnTriggerInputPin(const char *msg, brain_pin_e brainPin, bool isVvtShaft); #endif /* CRANK_INPUT_H_ */ diff --git a/firmware/hw_layer/trigger_input_icu.cpp b/firmware/hw_layer/trigger_input_icu.cpp index 7d4e216383..bfdf516bd5 100644 --- a/firmware/hw_layer/trigger_input_icu.cpp +++ b/firmware/hw_layer/trigger_input_icu.cpp @@ -28,13 +28,15 @@ extern bool hasFirmwareErrorFlag; static Logging *logger; -static void vvtWidthCallback(void *arg) { - (void)arg; +static ICUDriver *primaryCrankDriver; + +static void cam_icu_width_callback(ICUDriver *icup) { + (void)icup; hwHandleVvtCamSignal(TV_RISE); } -static void vvtPeriodCallback(void *arg) { - (void)arg; +static void cam_icu_period_callback(ICUDriver *icup) { + (void)icup; hwHandleVvtCamSignal(TV_FALL); } @@ -42,7 +44,7 @@ static void vvtPeriodCallback(void *arg) { * that's hardware timer input capture IRQ entry point * 'width' events happens before the 'period' event */ -static void shaftWidthCallback(bool isPrimary) { +static void shaft_icu_width_callback(ICUDriver *icup) { if (!engine->hwTriggerInputEnabled) { return; } @@ -51,6 +53,7 @@ static void shaftWidthCallback(bool isPrimary) { // 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; } @@ -61,13 +64,14 @@ static void shaftWidthCallback(bool isPrimary) { hwHandleShaftSignal(signal); } -static void shaftPeriodCallback(bool isPrimary) { +static void shaft_icu_period_callback(ICUDriver *icup) { if (!engine->hwTriggerInputEnabled) { return; } icuWidthPeriodCounter++; if (hasFirmwareErrorFlag) return; + int isPrimary = icup == primaryCrankDriver; if (!isPrimary && !TRIGGER_SHAPE(needSecondTriggerInput)) { return; } @@ -79,31 +83,83 @@ static void shaftPeriodCallback(bool isPrimary) { hwHandleShaftSignal(signal); } -void turnOnTriggerInputPin(const char *msg, int index, bool isTriggerShaft) { +/** + * 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; - brain_pin_e brainPin = isTriggerShaft ? CONFIGB(triggerInputPins)[index] : engineConfiguration->camInputs[index]; if (brainPin == GPIO_UNASSIGNED) { - return; + return -1; } - digital_input_s* input = startDigitalCapture("trigger", brainPin, true); - if (isTriggerShaft) { - void * arg = (void*) (index == 0); - input->setWidthCallback((VoidInt)(void*)shaftWidthCallback, arg); - input->setPeriodCallback((VoidInt)(void*)shaftPeriodCallback, arg); + if (isVvtShaft) { + icucfg = &shaft_icucfg; } else { - input->setWidthCallback((VoidInt)(void*)vvtWidthCallback, NULL); - input->setPeriodCallback((VoidInt)(void*)vvtPeriodCallback, NULL); + 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; } void turnOffTriggerInputPin(brain_pin_e brainPin) { - - stopDigitalCapture("trigger", brainPin); + ICUDriver *driver = getInputCaptureDriver("trigger_off", brainPin); + if (driver != NULL) { + icuDisableNotifications(driver); + icuStopCapture(driver); + icuStop(driver); + scheduleMsg(logger, "turnOffTriggerInputPin %s", hwPortname(brainPin)); + turnOffCapturePin(brainPin); + } } void setPrimaryChannel(brain_pin_e brainPin) { - + primaryCrankDriver = getInputCaptureDriver("primary", brainPin); } /*==========================================================================*/