diff --git a/firmware/controllers/trigger/trigger.mk b/firmware/controllers/trigger/trigger.mk index 6446aa0a38..eff136a6d3 100644 --- a/firmware/controllers/trigger/trigger.mk +++ b/firmware/controllers/trigger/trigger.mk @@ -7,6 +7,7 @@ TRIGGER_DECODERS_SRC_CPP = \ $(PROJECT_DIR)/controllers/trigger/trigger_chrysler.cpp \ $(PROJECT_DIR)/controllers/trigger/trigger_structure.cpp \ $(PROJECT_DIR)/controllers/trigger/trigger_decoder.cpp \ + $(PROJECT_DIR)/controllers/trigger/trigger_simulator.cpp \ $(PROJECT_DIR)/controllers/trigger/trigger_mitsubishi.cpp \ $(PROJECT_DIR)/controllers/trigger/trigger_nissan.cpp \ $(PROJECT_DIR)/controllers/trigger/trigger_subaru.cpp \ diff --git a/firmware/controllers/trigger/trigger_decoder.cpp b/firmware/controllers/trigger/trigger_decoder.cpp index d3c09ce0ed..4ba4e76582 100644 --- a/firmware/controllers/trigger/trigger_decoder.cpp +++ b/firmware/controllers/trigger/trigger_decoder.cpp @@ -38,6 +38,7 @@ #include "engine.h" #include "engine_math.h" #include "trigger_central.h" +#include "trigger_simulator.h" #if EFI_SENSOR_CHART || defined(__DOXYGEN__) #include "sensor_chart.h" @@ -48,9 +49,6 @@ static OutputPin triggerDecoderErrorPin; EXTERN_ENGINE ; -// todo: better name for this constant -#define HELPER_PERIOD 720000 - static cyclic_buffer errorDetection; #if ! EFI_PROD_CODE || defined(__DOXYGEN__) @@ -503,47 +501,6 @@ void TriggerShape::initializeTriggerShape(Logging *logger DECLARE_ENGINE_PARAMET calculateTriggerSynchPoint(&engine->triggerCentral.triggerState PASS_ENGINE_PARAMETER); } -TriggerStimulatorHelper::TriggerStimulatorHelper() { -} - -void TriggerStimulatorHelper::nextStep(TriggerState *state, TriggerShape * shape, int i, - trigger_config_s const*triggerConfig DECLARE_ENGINE_PARAMETER_S) { - int stateIndex = i % shape->getSize(); - int prevIndex = (stateIndex + shape->getSize() - 1 ) % shape->getSize(); - - - int loopIndex = i / shape->getSize(); - - int time = (int) (HELPER_PERIOD * (loopIndex + shape->wave.getSwitchTime(stateIndex))); - - bool_t primaryWheelState = shape->wave.getChannelState(0, prevIndex); - bool_t newPrimaryWheelState = shape->wave.getChannelState(0, stateIndex); - - bool_t secondaryWheelState = shape->wave.getChannelState(1, prevIndex); - bool_t newSecondaryWheelState = shape->wave.getChannelState(1, stateIndex); - - bool_t thirdWheelState = shape->wave.getChannelState(2, prevIndex); - bool_t new3rdWheelState = shape->wave.getChannelState(2, stateIndex); - - if (primaryWheelState != newPrimaryWheelState) { - primaryWheelState = newPrimaryWheelState; - trigger_event_e s = primaryWheelState ? SHAFT_PRIMARY_UP : SHAFT_PRIMARY_DOWN; - state->decodeTriggerEvent(s, time PASS_ENGINE_PARAMETER); - } - - if (secondaryWheelState != newSecondaryWheelState) { - secondaryWheelState = newSecondaryWheelState; - trigger_event_e s = secondaryWheelState ? SHAFT_SECONDARY_UP : SHAFT_SECONDARY_DOWN; - state->decodeTriggerEvent(s, time PASS_ENGINE_PARAMETER); - } - - if (thirdWheelState != new3rdWheelState) { - thirdWheelState = new3rdWheelState; - trigger_event_e s = thirdWheelState ? SHAFT_3RD_UP : SHAFT_3RD_DOWN; - state->decodeTriggerEvent(s, time PASS_ENGINE_PARAMETER); - } -} - static void onFindIndex(TriggerState *state) { for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) { // todo: that's not the best place for this intermediate data storage, fix it! @@ -551,18 +508,6 @@ static void onFindIndex(TriggerState *state) { } } -static uint32_t doFindTrigger(TriggerStimulatorHelper *helper, TriggerShape * shape, - trigger_config_s const*triggerConfig, TriggerState *state DECLARE_ENGINE_PARAMETER_S) { - for (int i = 0; i < 4 * PWM_PHASE_MAX_COUNT; i++) { - helper->nextStep(state, shape, i, triggerConfig PASS_ENGINE_PARAMETER); - - if (state->shaft_is_synchronized) - return i; - } - firmwareError("findTriggerZeroEventIndex() failed"); - return EFI_ERROR_CODE; -} - /** * Trigger shape is defined in a way which is convenient for trigger shape definition * On the other hand, trigger decoder indexing begins from synchronization event. @@ -582,7 +527,7 @@ DECLARE_ENGINE_PARAMETER_S) { // todo: should this variable be declared 'static' to reduce stack usage? TriggerStimulatorHelper helper; - uint32_t index = doFindTrigger(&helper, shape, triggerConfig, state PASS_ENGINE_PARAMETER); + uint32_t index = helper.doFindTrigger(shape, triggerConfig, state PASS_ENGINE_PARAMETER); if (index == EFI_ERROR_CODE) { return index; } @@ -596,18 +541,7 @@ DECLARE_ENGINE_PARAMETER_S) { */ state->cycleCallback = onFindIndex; - int startIndex = engineConfiguration->useOnlyFrontForTrigger ? index + 2 : index + 1; - - for (uint32_t i = startIndex; i <= index + 2 * shape->getSize(); i++) { - helper.nextStep(state, shape, i, triggerConfig PASS_ENGINE_PARAMETER); - if (engineConfiguration->useOnlyFrontForTrigger) - i++; - } - efiAssert(state->getTotalRevolutionCounter() == 3, "totalRevolutionCounter2 expected 3", EFI_ERROR_CODE); - - for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) { - shape->dutyCycle[i] = 1.0 * state->expectedTotalTime[i] / HELPER_PERIOD; - } + helper.assertSyncPositionAndSetDutyCycle(index, state, shape,triggerConfig PASS_ENGINE_PARAMETER); return index % shape->getSize(); } diff --git a/firmware/controllers/trigger/trigger_decoder.h b/firmware/controllers/trigger/trigger_decoder.h index ef60d9d5d2..ba7c56e3ab 100644 --- a/firmware/controllers/trigger/trigger_decoder.h +++ b/firmware/controllers/trigger/trigger_decoder.h @@ -104,12 +104,6 @@ private: efitick_t startOfCycleNt; }; -class TriggerStimulatorHelper { -public: - TriggerStimulatorHelper(); - void nextStep(TriggerState *state, TriggerShape * shape, int i, trigger_config_s const*triggerConfig DECLARE_ENGINE_PARAMETER_S); -}; - float getEngineCycle(operation_mode_e operationMode); void addSkippedToothTriggerEvents(trigger_wheel_e wheel, TriggerShape *s, int totalTeethCount, int skippedCount, diff --git a/firmware/controllers/trigger/trigger_emulator_algo.cpp b/firmware/controllers/trigger/trigger_emulator_algo.cpp index aa0d4e9cc3..d6db8628ce 100644 --- a/firmware/controllers/trigger/trigger_emulator_algo.cpp +++ b/firmware/controllers/trigger/trigger_emulator_algo.cpp @@ -1,6 +1,15 @@ /** * @file trigger_emulator_algo.cpp * + * This file is about producing real electrical signals which emulate trigger signal based on + * a known TriggerShape. + * + * Historically this implementation was implemented based on PwmConfig which is maybe not the + * best way to implement it. (todo: why is not the best way?) + * + * A newer implementation of pretty much the same thing is TriggerStimulatorHelper + * todo: one emulator should be enough! another one should be eliminated + * * @date Mar 3, 2014 * @author Andrey Belomutskiy, (c) 2012-2015 */ diff --git a/firmware/controllers/trigger/trigger_simulator.cpp b/firmware/controllers/trigger/trigger_simulator.cpp new file mode 100644 index 0000000000..0258142f33 --- /dev/null +++ b/firmware/controllers/trigger/trigger_simulator.cpp @@ -0,0 +1,84 @@ +/* + * @file trigger_simulator.cpp + * + * @date Sep 23, 2015 + * @author Andrey Belomutskiy, (c) 2012-2015 + */ + +#include "main.h" +#include "engine.h" +#include "trigger_simulator.h" + +#define SIMULATION_CYCLE_PERIOD 720000 + +EXTERN_ENGINE; + +TriggerStimulatorHelper::TriggerStimulatorHelper() { +} + +void TriggerStimulatorHelper::nextStep(TriggerState *state, TriggerShape * shape, int i, + trigger_config_s const*triggerConfig DECLARE_ENGINE_PARAMETER_S) { + int stateIndex = i % shape->getSize(); + int prevIndex = (stateIndex + shape->getSize() - 1 ) % shape->getSize(); + + + int loopIndex = i / shape->getSize(); + + int time = (int) (SIMULATION_CYCLE_PERIOD * (loopIndex + shape->wave.getSwitchTime(stateIndex))); + + bool_t primaryWheelState = shape->wave.getChannelState(0, prevIndex); + bool_t newPrimaryWheelState = shape->wave.getChannelState(0, stateIndex); + + bool_t secondaryWheelState = shape->wave.getChannelState(1, prevIndex); + bool_t newSecondaryWheelState = shape->wave.getChannelState(1, stateIndex); + + bool_t thirdWheelState = shape->wave.getChannelState(2, prevIndex); + bool_t new3rdWheelState = shape->wave.getChannelState(2, stateIndex); + + if (primaryWheelState != newPrimaryWheelState) { + primaryWheelState = newPrimaryWheelState; + trigger_event_e s = primaryWheelState ? SHAFT_PRIMARY_UP : SHAFT_PRIMARY_DOWN; + state->decodeTriggerEvent(s, time PASS_ENGINE_PARAMETER); + } + + if (secondaryWheelState != newSecondaryWheelState) { + secondaryWheelState = newSecondaryWheelState; + trigger_event_e s = secondaryWheelState ? SHAFT_SECONDARY_UP : SHAFT_SECONDARY_DOWN; + state->decodeTriggerEvent(s, time PASS_ENGINE_PARAMETER); + } + + if (thirdWheelState != new3rdWheelState) { + thirdWheelState = new3rdWheelState; + trigger_event_e s = thirdWheelState ? SHAFT_3RD_UP : SHAFT_3RD_DOWN; + state->decodeTriggerEvent(s, time PASS_ENGINE_PARAMETER); + } +} + +void TriggerStimulatorHelper::assertSyncPositionAndSetDutyCycle(uint32_t index, TriggerState *state, TriggerShape * shape, + trigger_config_s const*triggerConfig DECLARE_ENGINE_PARAMETER_S) { + int startIndex = engineConfiguration->useOnlyFrontForTrigger ? index + 2 : index + 1; + + for (uint32_t i = startIndex; i <= index + 2 * shape->getSize(); i++) { + nextStep(state, shape, i, triggerConfig PASS_ENGINE_PARAMETER); + if (engineConfiguration->useOnlyFrontForTrigger) + i++; + } + // todo: nicer error handling? + efiAssertVoid(state->getTotalRevolutionCounter() == 3, "totalRevolutionCounter2 expected 3"); + + for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) { + shape->dutyCycle[i] = 1.0 * state->expectedTotalTime[i] / SIMULATION_CYCLE_PERIOD; + } +} + +uint32_t TriggerStimulatorHelper::doFindTrigger(TriggerShape * shape, + trigger_config_s const*triggerConfig, TriggerState *state DECLARE_ENGINE_PARAMETER_S) { + for (int i = 0; i < 4 * PWM_PHASE_MAX_COUNT; i++) { + nextStep(state, shape, i, triggerConfig PASS_ENGINE_PARAMETER); + + if (state->shaft_is_synchronized) + return i; + } + firmwareError("findTriggerZeroEventIndex() failed"); + return EFI_ERROR_CODE; +} diff --git a/firmware/controllers/trigger/trigger_simulator.h b/firmware/controllers/trigger/trigger_simulator.h new file mode 100644 index 0000000000..cba53f18ae --- /dev/null +++ b/firmware/controllers/trigger/trigger_simulator.h @@ -0,0 +1,28 @@ +/* + * @file trigger_simulator.h + * @brief This class knows how to produce synthetic shaft signals based on triggerShape + * + * @date Sep 23, 2015 + * @author Andrey Belomutskiy, (c) 2012-2015 + */ + +#ifndef CONTROLLERS_TRIGGER_TRIGGER_SIMULATOR_H_ +#define CONTROLLERS_TRIGGER_TRIGGER_SIMULATOR_H_ + +#include "trigger_decoder.h" + +class TriggerStimulatorHelper { +public: + TriggerStimulatorHelper(); + + uint32_t doFindTrigger(TriggerShape * shape, + trigger_config_s const*triggerConfig, TriggerState *state DECLARE_ENGINE_PARAMETER_S); + + void nextStep(TriggerState *state, TriggerShape * shape, int i, trigger_config_s const*triggerConfig DECLARE_ENGINE_PARAMETER_S); + + void assertSyncPositionAndSetDutyCycle(uint32_t index, TriggerState *state, TriggerShape * shape, + trigger_config_s const*triggerConfig DECLARE_ENGINE_PARAMETER_S); +}; + + +#endif /* CONTROLLERS_TRIGGER_TRIGGER_SIMULATOR_H_ */