rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
trigger_input_comp.cpp
Go to the documentation of this file.
1/**
2 * @file trigger_input_comp.cpp
3 * @brief Position sensor hardware layer, Using hardware comparator
4 *
5 * @date Apr 13, 2019
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 * @author andreika <prometheus.pcb@gmail.com>
8 */
9
10#include "pch.h"
11
12#if (EFI_SHAFT_POSITION_INPUT && HAL_USE_COMP) || defined(__DOXYGEN__)
13
14#include "hal_comp.h"
15
16#include "trigger_input.h"
17
18static volatile int centeredDacValue = 127;
19static volatile int toothCnt = 0;
20static volatile int dacHysteresisMin = 1; // = 5V * 1/256 (8-bit DAC) = ~20mV
21static volatile int dacHysteresisMax = 15; // = ~300mV
23static volatile int hystUpdatePeriodNumEvents = 116; // every ~1 turn of 60-2 wheel
24static volatile efitick_t prevNt = 0;
25// VR-sensor saturation stuff
26static volatile float curVrFreqNt = 0, saturatedVrFreqNt = 0;
27
28// We want to interpolate between min and max depending on the signal level (adaptive hysteresis).
29// But we don't want to measure the signal amplitude directly, so we estimate it by measuring the signal frequency:
30// for VR sensors, the amplitude is inversely proportional to the tooth's 'time-width'.
31// We find it by dividing the total time by the teeth count, and use the reciprocal value as signal frequency!
32static void setHysteresis(COMPDriver *comp, int sign) {
33 // update the hysteresis threshold, but not for every tooth
34#ifdef EFI_TRIGGER_COMP_ADAPTIVE_HYSTERESIS
36 efitick_t nowNt = getTimeNowNt();
37 curVrFreqNt = (float)toothCnt / (float)(nowNt - prevNt);
39 toothCnt = 0;
40 prevNt = nowNt;
41#ifdef TRIGGER_COMP_EXTREME_LOGGING
42 efiPrintf("* f=%f d=%d", curVrFreqNt * 1000.0f, dacHysteresisDelta);
43#endif /* TRIGGER_COMP_EXTREME_LOGGING */
44 }
45#endif /* EFI_TRIGGER_COMP_ADAPTIVE_HYSTERESIS */
47}
48
49static void comp_shaft_callback(COMPDriver *comp) {
50 efitick_t stamp = getTimeNowNt();
51
52 uint32_t status = comp_lld_get_status(comp);
53 int isPrimary = (comp == EFI_COMP_PRIMARY_DEVICE);
54
55 if (status & COMP_IRQ_RISING) {
56 hwHandleShaftSignal(isPrimary ? 0 : 1, true, stamp);
57 // shift the threshold down a little bit to avoid false-triggering (threshold hysteresis)
58 setHysteresis(comp, -1);
59 }
60
61 if (status & COMP_IRQ_FALLING) {
62 hwHandleShaftSignal(isPrimary ? 0 : 1, false, stamp);
63 // shift the threshold up a little bit to avoid false-triggering (threshold hysteresis)
64 setHysteresis(comp, 1);
65 }
66}
67
68// todo: add cam support?
69#if 0
70static void comp_cam_callback(COMPDriver *comp) {
71 efitick_t stamp = getTimeNowNt();
72
73 hwHandleVvtCamSignal(isRising, stamp, index);
74}
75#endif
76
82
83static bool isCompEnabled = false;
84
86 compInit();
87 compStart(EFI_COMP_PRIMARY_DEVICE, &comp_shaft_cfg);
88}
89
90static int getDacValue(uint8_t voltage) {
91 constexpr float maxDacValue = 255.0f; // 8-bit DAC
92 return (int)efiRound(maxDacValue * (float)voltage * VOLTAGE_1_BYTE_PACKING_DIV / engineConfiguration->adcVcc, 1.0f);
93}
94
96 if (isCompEnabled) {
97 efiPrintf("startTIPins(): already enabled!");
98 return;
99 }
100
101 centeredDacValue = getDacValue(engineConfiguration->triggerCompCenterVolt); // usually 2.5V resistor divider
102
106
107 // 20 rpm (60_2) = 1000*60/((2*60)*20) = 25 ms for 1 tooth event
109 hystUpdatePeriodNumEvents = engine->triggerCentral.triggerShape.getSize(); // = 116 for "60-2" trigger wheel
110 float saturatedToothDurationUs = 60.0f * US_PER_SECOND_F / satRpm / hystUpdatePeriodNumEvents;
111 saturatedVrFreqNt = 1.0f / US2NT(saturatedToothDurationUs);
112
113 efiPrintf("startTIPins(): cDac=%d hystMin=%d hystMax=%d satRpm=%.0f satFreq*1k=%f period=%d",
115#ifdef EFI_TRIGGER_COMP_ADAPTIVE_HYSTERESIS
116 efiPrintf("startTIPins(): ADAPTIVE_HYSTERESIS enabled!");
117#endif /* EFI_TRIGGER_COMP_ADAPTIVE_HYSTERESIS */
118
119 int channel = EFI_COMP_TRIGGER_CHANNEL; // todo: use getInputCaptureChannel(hwPin);
120
121 // todo: set pin mode to default (analog/comparator)
122 //palSetPadMode(comp_channel_port[channel], comp_channel_pad[channel], PAL_MODE_INPUT_ANALOG);
123
124 // no generic hal support for extended COMP configuration, so we use hal_lld layer...
125 osalSysLock();
126 comp_lld_set_dac_value(EFI_COMP_PRIMARY_DEVICE, centeredDacValue);
127 comp_lld_channel_enable(EFI_COMP_PRIMARY_DEVICE, channel);
128 osalSysUnlock();
129
130 compEnable(EFI_COMP_PRIMARY_DEVICE);
131 isCompEnabled = true;
132}
133
135 if (!isCompEnabled) {
136 efiPrintf("stopTIPins(): already disabled!");
137 return;
138 }
139
140 efiPrintf("stopTIPins();");
141
142 compDisable(EFI_COMP_PRIMARY_DEVICE);
143 isCompEnabled = false;
144#if 0
145 for (int i = 0; i < TRIGGER_INPUT_PIN_COUNT; i++) {
146 if (isConfigurationChanged(bc.triggerInputPins[i])) {
148 }
149 }
150 if (isConfigurationChanged(camInput)) {
152 }
153#endif
154}
155
156#endif /* EFI_SHAFT_POSITION_INPUT && HAL_USE_COMP */
uint16_t channel
Definition adc_inputs.h:104
TriggerCentral triggerCentral
Definition engine.h:318
TriggerWaveform triggerShape
size_t getSize() const
float interpolateClamped(float x1, float y1, float x2, float y2, float x)
float efiRound(float value, float precision)
Definition efilib.cpp:34
efitick_t getTimeNowNt()
Definition efitime.cpp:19
static EngineAccessor engine
Definition engine.h:413
engine_configuration_s & activeConfiguration
static constexpr engine_configuration_s * engineConfiguration
void comp_lld_set_dac_value(COMPDriver *compp, uint32_t value)
Set the DAC value used by comp.
void comp_lld_channel_enable(COMPDriver *compp, uint32_t channel)
Configures and activates an EXT channel (used by comp)
uint32_t comp_lld_get_status(COMPDriver *compp)
@ COMP_OUTPUT_NORMAL
@ COMP_IRQ_FALLING
@ COMP_IRQ_RISING
@ COMP_IRQ_BOTH
Driver configuration structure.
Structure representing an COMP driver.
brain_input_pin_e triggerInputPins[TRIGGER_INPUT_PIN_COUNT]
void hwHandleShaftSignal(int signalIndex, bool isRising, efitick_t timestamp)
void hwHandleVvtCamSignal(bool isRising, efitick_t nowNt, int index)
static void turnOffTriggerInputPin(int index, bool isTriggerShaft)
Position sensor hardware layer.
static COMPConfig comp_shaft_cfg
static volatile float saturatedVrFreqNt
static volatile int toothCnt
static void comp_shaft_callback(COMPDriver *comp)
void stopTriggerInputPins()
static volatile int centeredDacValue
static volatile int hystUpdatePeriodNumEvents
void onEcuStartTriggerImplementation()
static volatile efitick_t prevNt
static int getDacValue(uint8_t voltage)
static bool isCompEnabled
static volatile int dacHysteresisMax
static void setHysteresis(COMPDriver *comp, int sign)
static void comp_cam_callback(COMPDriver *comp)
void startTriggerInputPins()
static volatile int dacHysteresisMin
static volatile float curVrFreqNt
static volatile int dacHysteresisDelta