2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file trigger_decoder.h
|
|
|
|
*
|
|
|
|
* @date Dec 24, 2013
|
2019-12-05 21:07:27 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2019
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
2019-12-05 21:07:27 -08:00
|
|
|
#pragma once
|
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
|
|
|
#include "trigger_structure.h"
|
|
|
|
#include "engine_configuration.h"
|
2019-09-03 16:30:51 -07:00
|
|
|
#include "trigger_state_generated.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
class TriggerState;
|
|
|
|
|
2019-12-05 22:57:11 -08:00
|
|
|
class TriggerStateListener {
|
|
|
|
public:
|
|
|
|
virtual void OnTriggerStateDecodingError() = 0;
|
|
|
|
virtual void OnTriggerStateProperState(efitick_t nowNt) = 0;
|
|
|
|
};
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
typedef void (*TriggerStateCallback)(TriggerState *);
|
|
|
|
|
2015-09-08 20:01:07 -07:00
|
|
|
typedef struct {
|
|
|
|
/**
|
|
|
|
* index within trigger revolution, from 0 to trigger event count
|
|
|
|
*/
|
|
|
|
uint32_t current_index;
|
|
|
|
/**
|
2015-09-12 13:01:43 -07:00
|
|
|
* Number of actual events of each channel within current trigger cycle, these
|
|
|
|
* values are used to detect trigger signal errors.
|
2019-12-07 22:09:39 -08:00
|
|
|
* see TriggerWaveform
|
2015-09-08 20:01:07 -07:00
|
|
|
*/
|
|
|
|
uint32_t eventCount[PWM_PHASE_MAX_WAVE_PER_PWM];
|
2015-09-12 13:01:43 -07:00
|
|
|
/**
|
|
|
|
* This array is used to calculate duty cycle of each trigger channel.
|
|
|
|
* Current implementation is a bit funny - it does not really consider if an event
|
|
|
|
* is a rise or a fall, it works based on the event order within synchronization cycle.
|
|
|
|
*
|
|
|
|
* 32 bit value is good enough here, overflows will happen but they would work just fine.
|
|
|
|
*/
|
|
|
|
uint32_t timeOfPreviousEventNt[PWM_PHASE_MAX_WAVE_PER_PWM];
|
|
|
|
/**
|
|
|
|
* Here we accumulate the amount of time this signal was ON within current trigger cycle
|
|
|
|
*/
|
|
|
|
uint32_t totalTimeNt[PWM_PHASE_MAX_WAVE_PER_PWM];
|
2015-09-08 20:01:07 -07:00
|
|
|
} current_cycle_state_s;
|
|
|
|
|
2018-02-05 14:16:34 -08:00
|
|
|
/**
|
2019-12-07 22:09:39 -08:00
|
|
|
* @see TriggerWaveform for trigger wheel shape definition
|
2018-02-05 14:16:34 -08:00
|
|
|
*/
|
2019-09-03 16:30:51 -07:00
|
|
|
class TriggerState : public trigger_state_s {
|
2015-07-10 06:01:56 -07:00
|
|
|
public:
|
|
|
|
TriggerState();
|
2018-02-05 14:16:34 -08:00
|
|
|
/**
|
|
|
|
* current trigger processing index, between zero and #size
|
|
|
|
*/
|
2019-01-15 17:24:36 -08:00
|
|
|
int getCurrentIndex() const;
|
|
|
|
int getTotalRevolutionCounter() const;
|
2016-08-23 19:02:18 -07:00
|
|
|
/**
|
|
|
|
* this is important for crank-based virtual trigger and VVT magic
|
|
|
|
*/
|
2019-01-15 17:24:36 -08:00
|
|
|
bool isEvenRevolution() const;
|
2018-02-05 14:16:34 -08:00
|
|
|
void incrementTotalEventCounter();
|
2019-01-23 18:43:27 -08:00
|
|
|
efitime_t getTotalEventCounter() const;
|
2019-12-05 22:05:19 -08:00
|
|
|
|
|
|
|
void decodeTriggerEvent(const TriggerStateCallback triggerCycleCallback,
|
2019-12-05 22:57:11 -08:00
|
|
|
TriggerStateListener * triggerStateListener,
|
2019-12-05 22:05:19 -08:00
|
|
|
trigger_event_e const signal, efitime_t nowUs DECLARE_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
|
2019-01-23 19:06:42 -08:00
|
|
|
bool validateEventCounters(DECLARE_ENGINE_PARAMETER_SIGNATURE) const;
|
|
|
|
void handleTriggerError(DECLARE_ENGINE_PARAMETER_SIGNATURE);
|
2019-12-05 22:05:19 -08:00
|
|
|
void onShaftSynchronization(const TriggerStateCallback triggerCycleCallback,
|
2019-12-21 18:11:09 -08:00
|
|
|
efitick_t nowNt, trigger_wheel_e triggerWheel DECLARE_ENGINE_PARAMETER_SUFFIX);
|
2018-03-03 16:26:59 -08:00
|
|
|
/**
|
|
|
|
* Resets synchronization flag and alerts rpm_calculator to reset engine spinning flag.
|
|
|
|
*/
|
|
|
|
void onSynchronizationLost(DECLARE_ENGINE_PARAMETER_SIGNATURE);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-06-08 06:51:36 -07:00
|
|
|
bool isValidIndex(DECLARE_ENGINE_PARAMETER_SIGNATURE) const;
|
2015-07-10 06:01:56 -07:00
|
|
|
float getTriggerDutyCycle(int index);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TRUE if we know where we are
|
|
|
|
*/
|
|
|
|
bool shaft_is_synchronized;
|
2019-12-21 18:11:09 -08:00
|
|
|
efitick_t mostRecentSyncTime;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-01-15 18:18:44 -08:00
|
|
|
efitick_t lastDecodingErrorTime;
|
|
|
|
// the boolean flag is a performance optimization so that complex comparison is avoided if no error
|
|
|
|
bool someSortOfTriggerError;
|
|
|
|
|
2018-10-21 09:29:41 -07:00
|
|
|
/**
|
|
|
|
* current duration at index zero and previous durations are following
|
|
|
|
*/
|
2018-10-23 00:47:30 -07:00
|
|
|
uint32_t toothDurations[GAP_TRACKING_LENGTH + 1];
|
2018-10-21 08:27:14 -07:00
|
|
|
|
2019-12-21 18:11:09 -08:00
|
|
|
efitick_t toothed_previous_time;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2015-09-08 20:01:07 -07:00
|
|
|
current_cycle_state_s currentCycle;
|
2017-12-12 15:04:54 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
int expectedTotalTime[PWM_PHASE_MAX_WAVE_PER_PWM];
|
2015-09-12 14:01:24 -07:00
|
|
|
|
2015-08-17 20:02:01 -07:00
|
|
|
/**
|
|
|
|
* how many times since ECU reboot we had unexpected number of teeth in trigger cycle
|
|
|
|
*/
|
2015-07-10 06:01:56 -07:00
|
|
|
uint32_t totalTriggerErrorCounter;
|
|
|
|
uint32_t orderingErrorCounter;
|
|
|
|
|
2019-01-22 16:07:36 -08:00
|
|
|
void resetTriggerState();
|
2019-08-18 12:53:38 -07:00
|
|
|
void setShaftSynchronized(bool value);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
|
2019-12-21 18:11:09 -08:00
|
|
|
virtual void runtimeStatistics(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX);
|
2019-01-31 14:55:23 -08:00
|
|
|
#endif
|
2017-05-18 13:16:55 -07:00
|
|
|
|
2016-08-22 20:04:55 -07:00
|
|
|
/**
|
|
|
|
* this is start of real trigger cycle
|
|
|
|
* for virtual double trigger see timeAtVirtualZeroNt
|
|
|
|
*/
|
2016-08-20 19:02:12 -07:00
|
|
|
efitick_t startOfCycleNt;
|
2015-07-10 06:01:56 -07:00
|
|
|
private:
|
2015-09-08 20:01:07 -07:00
|
|
|
void resetCurrentCycleState();
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
trigger_event_e curSignal;
|
|
|
|
trigger_event_e prevSignal;
|
2019-12-21 18:11:09 -08:00
|
|
|
int64_t totalEventCountBase;
|
2015-07-10 06:01:56 -07:00
|
|
|
uint32_t totalRevolutionCounter;
|
|
|
|
bool isFirstEvent;
|
|
|
|
};
|
|
|
|
|
2019-01-24 18:12:55 -08:00
|
|
|
// we only need 90 degrees of events so /4 or maybe even /8 should work?
|
|
|
|
#define PRE_SYNC_EVENTS (PWM_PHASE_MAX_COUNT / 4)
|
|
|
|
|
2017-05-18 13:39:04 -07:00
|
|
|
|
|
|
|
/**
|
2019-12-05 21:07:27 -08:00
|
|
|
* the reason for sub-class is simply to save RAM but not having statistics in the trigger initialization instance
|
2017-05-18 13:39:04 -07:00
|
|
|
*/
|
2017-05-18 13:16:55 -07:00
|
|
|
class TriggerStateWithRunningStatistics : public TriggerState {
|
|
|
|
public:
|
2017-12-13 18:08:34 -08:00
|
|
|
TriggerStateWithRunningStatistics();
|
2019-01-13 20:20:19 -08:00
|
|
|
float instantRpm = 0;
|
2017-12-03 20:58:48 -08:00
|
|
|
/**
|
|
|
|
* timestamp of each trigger wheel tooth
|
|
|
|
*/
|
2017-05-18 13:16:55 -07:00
|
|
|
uint32_t timeOfLastEvent[PWM_PHASE_MAX_COUNT];
|
2019-01-24 18:12:55 -08:00
|
|
|
|
|
|
|
int spinningEventIndex = 0;
|
|
|
|
// todo: change the implementation to reuse 'timeOfLastEvent'
|
|
|
|
uint32_t spinningEvents[PRE_SYNC_EVENTS];
|
2017-12-03 20:58:48 -08:00
|
|
|
/**
|
|
|
|
* instant RPM calculated at this trigger wheel tooth
|
|
|
|
*/
|
2017-05-18 13:16:55 -07:00
|
|
|
float instantRpmValue[PWM_PHASE_MAX_COUNT];
|
2018-03-10 17:58:51 -08:00
|
|
|
/**
|
|
|
|
* Stores last non-zero instant RPM value to fix early instability
|
|
|
|
*/
|
2019-01-13 20:20:19 -08:00
|
|
|
float prevInstantRpmValue = 0;
|
2019-01-24 18:12:55 -08:00
|
|
|
void movePreSynchTimestamps(DECLARE_ENGINE_PARAMETER_SIGNATURE);
|
2019-12-21 18:11:09 -08:00
|
|
|
float calculateInstantRpm(int *prevIndex, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX);
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
|
2019-12-21 18:11:09 -08:00
|
|
|
void runtimeStatistics(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) override;
|
2019-01-31 14:55:23 -08:00
|
|
|
#endif
|
2018-03-10 17:58:51 -08:00
|
|
|
/**
|
|
|
|
* Update timeOfLastEvent[] on every trigger event - even without synchronization
|
|
|
|
* Needed for early spin-up RPM detection.
|
|
|
|
*/
|
2019-12-21 18:11:09 -08:00
|
|
|
void setLastEventTimeForInstantRpm(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX);
|
2017-05-18 13:16:55 -07:00
|
|
|
};
|
|
|
|
|
2016-01-14 21:01:42 -08:00
|
|
|
angle_t getEngineCycle(operation_mode_e operationMode);
|
2019-12-07 22:09:39 -08:00
|
|
|
uint32_t findTriggerZeroEventIndex(TriggerState *state, TriggerWaveform * shape, trigger_config_s const*triggerConfig DECLARE_ENGINE_PARAMETER_SUFFIX);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
class Engine;
|
|
|
|
|
2019-09-19 18:41:52 -07:00
|
|
|
void initTriggerDecoder(DECLARE_ENGINE_PARAMETER_SIGNATURE);
|
2015-07-10 06:01:56 -07:00
|
|
|
void initTriggerDecoderLogger(Logging *sharedLogger);
|
|
|
|
|
2016-01-11 14:01:33 -08:00
|
|
|
bool isTriggerDecoderError(void);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-12-07 22:09:39 -08:00
|
|
|
void calculateTriggerSynchPoint(TriggerWaveform *shape, TriggerState *state DECLARE_ENGINE_PARAMETER_SUFFIX);
|
2018-12-25 19:47:29 -08:00
|
|
|
|