2015-07-10 06:01:56 -07:00
|
|
|
/*
|
|
|
|
* @file trigger_central.h
|
|
|
|
*
|
|
|
|
* @date Feb 23, 2014
|
2020-01-07 21:02:40 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
2019-12-23 18:56:16 -08:00
|
|
|
#pragma once
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
#include "rusefi_enums.h"
|
|
|
|
#include "listener_array.h"
|
|
|
|
#include "trigger_decoder.h"
|
2022-11-06 09:03:55 -08:00
|
|
|
#include "instant_rpm_calculator.h"
|
2019-09-03 16:30:51 -07:00
|
|
|
#include "trigger_central_generated.h"
|
2023-08-30 20:11:24 -07:00
|
|
|
#include <rusefi/timer.h>
|
2021-01-08 17:01:26 -08:00
|
|
|
#include "pin_repository.h"
|
2021-11-15 17:22:05 -08:00
|
|
|
#include "local_version_holder.h"
|
2022-09-15 18:55:15 -07:00
|
|
|
#include "cyclic_buffer.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-12-04 15:41:17 -08:00
|
|
|
#define MAP_CAM_BUFFER 64
|
2021-11-24 19:36:36 -08:00
|
|
|
|
2022-01-17 18:18:43 -08:00
|
|
|
#ifndef RPM_LOW_THRESHOLD
|
|
|
|
// no idea what is the best value, 25 is as good as any other guess
|
|
|
|
#define RPM_LOW_THRESHOLD 25
|
|
|
|
#endif
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
class Engine;
|
2021-11-16 01:15:29 -08:00
|
|
|
typedef void (*ShaftPositionListener)(trigger_event_e signal, uint32_t index, efitick_t edgeTimestamp);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-01-08 17:01:26 -08:00
|
|
|
#define HAVE_CAM_INPUT() (isBrainPinValid(engineConfiguration->camInputs[0]))
|
2019-05-10 18:56:33 -07:00
|
|
|
|
2020-01-27 21:16:33 -08:00
|
|
|
class TriggerNoiseFilter {
|
|
|
|
public:
|
|
|
|
void resetAccumSignalData();
|
|
|
|
bool noiseFilter(efitick_t nowNt,
|
2022-05-10 01:41:39 -07:00
|
|
|
TriggerDecoderBase* triggerState,
|
2021-11-16 01:15:29 -08:00
|
|
|
trigger_event_e signal);
|
2020-01-27 21:16:33 -08:00
|
|
|
|
|
|
|
efitick_t lastSignalTimes[HW_EVENT_TYPES];
|
|
|
|
efitick_t accumSignalPeriods[HW_EVENT_TYPES];
|
|
|
|
efitick_t accumSignalPrevPeriods[HW_EVENT_TYPES];
|
|
|
|
};
|
|
|
|
|
2017-05-18 13:16:55 -07:00
|
|
|
/**
|
|
|
|
* Maybe merge TriggerCentral and TriggerState classes into one class?
|
|
|
|
* Probably not: we have an instance of TriggerState which is used for trigger initialization,
|
|
|
|
* also composition probably better than inheritance here
|
|
|
|
*/
|
2021-11-16 13:52:11 -08:00
|
|
|
class TriggerCentral final : public trigger_central_s {
|
2015-07-10 06:01:56 -07:00
|
|
|
public:
|
|
|
|
TriggerCentral();
|
2022-11-06 08:05:57 -08:00
|
|
|
angle_t syncAndReport(int divider, int remainder);
|
2021-11-16 01:15:29 -08:00
|
|
|
void handleShaftSignal(trigger_event_e signal, efitick_t timestamp);
|
2019-06-08 06:51:36 -07:00
|
|
|
int getHwEventCounter(int index) const;
|
2015-07-10 06:01:56 -07:00
|
|
|
void resetCounters();
|
2019-09-02 11:47:05 -07:00
|
|
|
void validateCamVvtCounters();
|
2022-09-13 23:45:31 -07:00
|
|
|
void updateWaveform();
|
2020-01-09 10:19:11 -08:00
|
|
|
|
2022-11-06 08:56:18 -08:00
|
|
|
InstantRpmCalculator instantRpm;
|
|
|
|
|
2022-11-05 19:30:08 -07:00
|
|
|
void prepareTriggerShape() {
|
2022-11-05 19:42:33 -07:00
|
|
|
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
|
|
|
|
if (triggerShape.shapeDefinitionError) {
|
|
|
|
// Nothing to do here if there's a problem with the trigger shape
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
triggerFormDetails.prepareEventAngles(&triggerShape);
|
|
|
|
#endif
|
2022-11-05 19:30:08 -07:00
|
|
|
}
|
|
|
|
|
2022-09-13 23:06:52 -07:00
|
|
|
// this is useful at least for real hardware integration testing - maybe a proper solution would be to simply
|
|
|
|
// GND input pins instead of leaving them floating
|
|
|
|
bool hwTriggerInputEnabled = true;
|
|
|
|
|
2022-09-13 23:35:55 -07:00
|
|
|
cyclic_buffer<int> triggerErrorDetection;
|
|
|
|
|
2022-09-13 23:06:52 -07:00
|
|
|
/**
|
2023-03-27 01:13:04 -07:00
|
|
|
* See also triggerSimulatorRpm
|
2022-09-13 23:06:52 -07:00
|
|
|
*/
|
|
|
|
bool directSelfStimulation = false;
|
|
|
|
|
2022-09-13 22:53:17 -07:00
|
|
|
PrimaryTriggerConfiguration primaryTriggerConfiguration;
|
|
|
|
#if CAMS_PER_BANK == 1
|
|
|
|
VvtTriggerConfiguration vvtTriggerConfiguration[CAMS_PER_BANK] = {{"VVT1 ", 0}};
|
|
|
|
#else
|
|
|
|
VvtTriggerConfiguration vvtTriggerConfiguration[CAMS_PER_BANK] = {{"VVT1 ", 0}, {"VVT2 ", 1}};
|
|
|
|
#endif
|
|
|
|
|
2021-12-07 17:00:04 -08:00
|
|
|
LocalVersionHolder triggerVersion;
|
|
|
|
|
2022-09-13 23:24:41 -07:00
|
|
|
/**
|
|
|
|
* By the way:
|
|
|
|
* 'cranking' means engine is not stopped and the rpm are below crankingRpm
|
|
|
|
* 'running' means RPM are above crankingRpm
|
|
|
|
* 'spinning' means the engine is not stopped
|
|
|
|
*/
|
|
|
|
// todo: combine with other RpmCalculator fields?
|
|
|
|
/**
|
|
|
|
* this is set to true each time we register a trigger tooth signal
|
|
|
|
*/
|
|
|
|
bool isSpinningJustForWatchdog = false;
|
|
|
|
|
2021-12-07 17:00:04 -08:00
|
|
|
float mapCamPrevCycleValue = 0;
|
2021-12-09 19:16:42 -08:00
|
|
|
int prevChangeAtCycle = 0;
|
2021-12-07 17:00:04 -08:00
|
|
|
|
2022-09-13 23:35:55 -07:00
|
|
|
/**
|
|
|
|
* value of 'triggerShape.getLength()'
|
|
|
|
* pre-calculating this value is a performance optimization
|
|
|
|
*/
|
|
|
|
uint32_t engineCycleEventCount = 0;
|
2021-11-15 17:22:05 -08:00
|
|
|
/**
|
|
|
|
* true if a recent configuration change has changed any of the trigger settings which
|
|
|
|
* we have not adjusted for yet
|
|
|
|
*/
|
2022-09-15 20:07:08 -07:00
|
|
|
bool triggerConfigChangedOnLastConfigurationChange = false;
|
2021-11-15 17:22:05 -08:00
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
bool checkIfTriggerConfigChanged();
|
2022-09-15 20:07:08 -07:00
|
|
|
#if EFI_UNIT_TEST
|
2021-11-16 01:15:29 -08:00
|
|
|
bool isTriggerConfigChanged();
|
2022-09-15 20:07:08 -07:00
|
|
|
#endif // EFI_UNIT_TEST
|
2021-11-15 17:22:05 -08:00
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
bool isTriggerDecoderError();
|
2021-11-15 17:22:05 -08:00
|
|
|
|
2021-11-04 02:46:16 -07:00
|
|
|
expected<float> getCurrentEnginePhase(efitick_t nowNt) const;
|
|
|
|
|
2022-01-17 18:27:10 -08:00
|
|
|
float getSecondsSinceTriggerEvent(efitick_t nowNt) const {
|
2020-12-06 19:28:29 -08:00
|
|
|
return m_lastEventTimer.getElapsedSeconds(nowNt);
|
2020-12-03 08:13:45 -08:00
|
|
|
}
|
|
|
|
|
2022-01-17 18:00:49 -08:00
|
|
|
bool engineMovedRecently(efitick_t nowNt) const {
|
2022-01-17 18:27:10 -08:00
|
|
|
constexpr float oneRevolutionLimitInSeconds = 60.0 / RPM_LOW_THRESHOLD;
|
2022-01-24 15:15:18 -08:00
|
|
|
auto maxAverageToothTime = oneRevolutionLimitInSeconds / triggerShape.getSize();
|
|
|
|
|
|
|
|
// Some triggers may have long gaps (with many teeth), don't count that as stopped!
|
|
|
|
auto maxAllowedGap = maxAverageToothTime * 10;
|
|
|
|
|
|
|
|
// Clamp between 0.1 seconds ("instant" for a human) and worst case of one engine cycle on low tooth count wheel
|
|
|
|
maxAllowedGap = clampF(0.1f, maxAllowedGap, oneRevolutionLimitInSeconds);
|
|
|
|
|
2022-01-25 14:24:25 -08:00
|
|
|
return getSecondsSinceTriggerEvent(nowNt) < maxAllowedGap;
|
2022-01-17 18:00:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool engineMovedRecently() const {
|
|
|
|
return engineMovedRecently(getTimeNowNt());
|
2021-02-05 15:19:57 -08:00
|
|
|
}
|
|
|
|
|
2020-01-27 21:16:33 -08:00
|
|
|
TriggerNoiseFilter noiseFilter;
|
|
|
|
|
2021-10-23 16:01:31 -07:00
|
|
|
int vvtEventRiseCounter[CAM_INPUTS_COUNT];
|
|
|
|
int vvtEventFallCounter[CAM_INPUTS_COUNT];
|
|
|
|
|
2021-03-25 04:39:23 -07:00
|
|
|
angle_t getVVTPosition(uint8_t bankIndex, uint8_t camIndex);
|
2020-01-30 22:49:10 -08:00
|
|
|
|
2021-01-26 19:54:25 -08:00
|
|
|
#if EFI_UNIT_TEST
|
2020-05-09 23:36:01 -07:00
|
|
|
// latest VVT event position (could be not synchronization event)
|
2021-02-08 17:38:38 -08:00
|
|
|
angle_t currentVVTEventPosition[BANKS_COUNT][CAMS_PER_BANK];
|
2021-01-26 19:54:25 -08:00
|
|
|
#endif // EFI_UNIT_TEST
|
|
|
|
|
2020-05-09 23:36:01 -07:00
|
|
|
// synchronization event position
|
2021-02-08 17:38:38 -08:00
|
|
|
angle_t vvtPosition[BANKS_COUNT][CAMS_PER_BANK];
|
2020-05-09 23:36:01 -07:00
|
|
|
|
2022-04-16 14:24:31 -07:00
|
|
|
#if EFI_SHAFT_POSITION_INPUT
|
2022-05-10 01:41:39 -07:00
|
|
|
PrimaryTriggerDecoder triggerState;
|
2022-04-16 14:40:05 -07:00
|
|
|
#endif //EFI_SHAFT_POSITION_INPUT
|
2022-04-16 14:24:31 -07:00
|
|
|
|
2019-12-07 22:09:39 -08:00
|
|
|
TriggerWaveform triggerShape;
|
2017-03-01 19:18:25 -08:00
|
|
|
|
2022-05-31 21:55:34 -07:00
|
|
|
VvtTriggerDecoder vvtState[BANKS_COUNT][CAMS_PER_BANK] = {
|
|
|
|
{
|
|
|
|
"VVT B1 Int",
|
|
|
|
#if CAMS_PER_BANK >= 2
|
|
|
|
"VVT B1 Exh"
|
|
|
|
#endif
|
|
|
|
},
|
|
|
|
#if BANKS_COUNT >= 2
|
|
|
|
{
|
|
|
|
"VVT B2 Int",
|
|
|
|
#if CAMS_PER_BANK >= 2
|
|
|
|
"VVT B1 Exh"
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2021-02-08 18:28:57 -08:00
|
|
|
TriggerWaveform vvtShape[CAMS_PER_BANK];
|
2020-08-24 22:24:15 -07:00
|
|
|
|
2020-08-24 21:59:07 -07:00
|
|
|
TriggerFormDetails triggerFormDetails;
|
2020-12-03 08:13:45 -08:00
|
|
|
|
|
|
|
// Keep track of the last time we got a valid trigger event
|
|
|
|
Timer m_lastEventTimer;
|
2021-11-04 02:46:16 -07:00
|
|
|
|
2022-09-13 23:17:04 -07:00
|
|
|
/**
|
|
|
|
* this is based on engineSnifferRpmThreshold settings and current RPM
|
|
|
|
*/
|
|
|
|
bool isEngineSnifferEnabled = false;
|
|
|
|
|
2021-11-14 12:04:10 -08:00
|
|
|
private:
|
2022-05-28 06:01:45 -07:00
|
|
|
void decodeMapCam(efitick_t nowNt, float currentPhase);
|
|
|
|
|
2023-01-10 13:07:17 -08:00
|
|
|
bool isToothExpectedNow(efitick_t timestamp);
|
|
|
|
|
2022-08-12 05:08:23 -07:00
|
|
|
// Time since the last tooth
|
|
|
|
Timer m_lastToothTimer;
|
|
|
|
// Phase of the last tooth relative to the sync point
|
|
|
|
float m_lastToothPhaseFromSyncPoint;
|
2022-09-23 20:49:28 -07:00
|
|
|
|
|
|
|
// At what engine phase do we expect the next tooth to arrive?
|
|
|
|
// Used for checking whether your trigger pattern is correct.
|
2023-01-10 13:07:17 -08:00
|
|
|
expected<float> expectedNextPhase = unexpected;
|
2015-07-10 06:01:56 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
void triggerInfo(void);
|
2021-11-16 01:15:29 -08:00
|
|
|
void hwHandleShaftSignal(int signalIndex, bool isRising, efitick_t timestamp);
|
|
|
|
void handleShaftSignal(int signalIndex, bool isRising, efitick_t timestamp);
|
2022-09-10 23:57:35 -07:00
|
|
|
void hwHandleVvtCamSignal(TriggerValue front, efitick_t timestamp, int index);
|
2023-02-28 02:11:28 -08:00
|
|
|
void hwHandleVvtCamSignal(bool isRising, efitick_t timestamp, int index);
|
2017-12-12 14:36:49 -08:00
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
void validateTriggerInputs();
|
2021-08-03 19:14:22 -07:00
|
|
|
|
2021-04-21 11:28:48 -07:00
|
|
|
void initTriggerCentral();
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
int isSignalDecoderError(void);
|
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
void onConfigurationChangeTriggerCallback();
|
2020-08-23 23:01:50 -07:00
|
|
|
|
2020-02-14 10:02:27 -08:00
|
|
|
#define SYMMETRICAL_CRANK_SENSOR_DIVIDER 4
|
2021-07-05 19:44:20 -07:00
|
|
|
#define SYMMETRICAL_THREE_TIMES_CRANK_SENSOR_DIVIDER 6
|
2022-05-17 18:38:24 -07:00
|
|
|
#define SYMMETRICAL_TWELVE_TIMES_CRANK_SENSOR_DIVIDER 24
|
2022-09-13 23:06:52 -07:00
|
|
|
|
|
|
|
TriggerCentral * getTriggerCentral();
|