hellen81 ADC trigger

This commit is contained in:
Andreika 2021-10-06 13:57:04 -04:00 committed by rusefillc
parent 1047fed77c
commit ada89312b5
6 changed files with 234 additions and 240 deletions

View File

@ -66,17 +66,6 @@ AdcDevice::AdcDevice(ADCConversionGroup* hwConfig, adcsample_t *buf, size_t buf_
memset(internalAdcIndexByHardwareIndex, 0xFF, sizeof(internalAdcIndexByHardwareIndex));
}
#if !defined(GPT_FREQ_FAST) || !defined(GPT_PERIOD_FAST)
/**
* 8000 RPM is 133Hz
* If we want to sample MAP once per 5 degrees we need 133Hz * (360 / 5) = 9576Hz of fast ADC
*/
// todo: migrate to continuous ADC mode? probably not - we cannot afford the callback in
// todo: continuous mode. todo: look into our options
#define GPT_FREQ_FAST 100000 /* PWM clock frequency. I wonder what does this setting mean? */
#define GPT_PERIOD_FAST 10 /* PWM period (in PWM ticks). */
#endif /* GPT_FREQ_FAST GPT_PERIOD_FAST */
#endif // EFI_USE_FAST_ADC
// is there a reason to have this configurable at runtime?

View File

@ -62,6 +62,17 @@ void removeChannel(const char *name, adc_channel_e setting);
#define adcToVoltsDivided(adc) (adcToVolts(adc) * engineConfiguration->analogInputDividerCoefficient)
#if !defined(GPT_FREQ_FAST) || !defined(GPT_PERIOD_FAST)
/**
* 8000 RPM is 133Hz
* If we want to sample MAP once per 5 degrees we need 133Hz * (360 / 5) = 9576Hz of fast ADC
*/
// todo: migrate to continuous ADC mode? probably not - we cannot afford the callback in
// todo: continuous mode. todo: look into our options
#define GPT_FREQ_FAST 100000 /* PWM clock frequency. I wonder what does this setting mean? */
#define GPT_PERIOD_FAST 10 /* PWM period (in PWM ticks). */
#endif /* GPT_FREQ_FAST GPT_PERIOD_FAST */
// This callback is called by the ADC driver when a new fast ADC sample is ready
void onFastAdcComplete(adcsample_t* samples);

View File

@ -33,16 +33,20 @@ void stopTriggerInputPins();
void stopTriggerDebugPins();
void startTriggerDebugPins();
#if HAL_TRIGGER_USE_ADC && HAL_USE_ADC
#if HAL_USE_ADC
typedef adcsample_t triggerAdcSample_t;
#endif /* HAL_USE_ADC */
// This detector has 2 modes for low-RPM (ADC) and fast-RPM (EXTI)
enum triggerAdcMode_t {
TRIGGER_NONE = 0,
TRIGGER_ADC,
TRIGGER_EXTI,
TRIGGER_ADC_NONE = 0,
TRIGGER_ADC_ADC,
TRIGGER_ADC_EXTI,
};
adc_channel_e getAdcChannelForTrigger(void);
void addAdcChannelForTrigger(void);
void triggerAdcCallback(adcsample_t value);
#endif /* HAL_USE_ADC */
void triggerAdcCallback(triggerAdcSample_t value);
void setTriggerAdcMode(triggerAdcMode_t adcMode);
void onTriggerChanged(efitick_t stamp, bool isPrimary, bool isRising);

View File

@ -8,202 +8,80 @@
*/
#include "pch.h"
#include "trigger_input_adc.h"
#if (EFI_SHAFT_POSITION_INPUT && HAL_TRIGGER_USE_ADC && HAL_USE_ADC) || defined(__DOXYGEN__)
#define voltsToAdcDivided(volts) (voltsToAdc(volts) / engineConfiguration->analogInputDividerCoefficient)
#include "trigger_input.h"
#include "digital_input_exti.h"
//!!!!!!!!!!!!!!!
extern "C" void toggleLed(int led, int mode);
#define BOARD_MOD1_PORT GPIOD
#define BOARD_MOD1_PIN 5
#if 0
static volatile int centeredDacValue = 127;
static volatile int toothCnt = 0;
static volatile int dacHysteresisMin = 1; // = 5V * 1/256 (8-bit DAC) = ~20mV
static volatile int dacHysteresisMax = 15; // = ~300mV
static volatile int dacHysteresisDelta = dacHysteresisMin;
static volatile int hystUpdatePeriodNumEvents = 116; // every ~1 turn of 60-2 wheel
static volatile efitick_t prevNt = 0;
// VR-sensor saturation stuff
static volatile float curVrFreqNt = 0, saturatedVrFreqNt = 0;
#endif
static const adcsample_t adcDefaultThreshold = (ADC_MAX_VALUE / 2);
static const adcsample_t adcMinThreshold = adcDefaultThreshold - 200;
static const adcsample_t adcMaxThreshold = adcDefaultThreshold + 200;
static float triggerAdcITermCoef = 1600.0f;
static float triggerAdcITermMin = 3.125e-8f; // corresponds to rpm=25
static int transitionCooldown = 5;
/*static*/ TriggerAdcDetector trigAdcState;
#define DELTA_THRESHOLD_CNT_LOW (GPT_FREQ_FAST / GPT_PERIOD_FAST / 32) // ~1/32 second?
#define DELTA_THRESHOLD_CNT_HIGH (GPT_FREQ_FAST / GPT_PERIOD_FAST / 4) // ~1/4 second?
/*static */triggerAdcMode_t curAdcMode = TRIGGER_NONE;
/*static*/ float adcThreshold = adcDefaultThreshold;
static float triggerAdcITerm = triggerAdcITermMin;
// these thresholds allow to switch from ADC mode (low-rpm) to EXTI mode (fast-rpm), indicating the clamping of the signal
static adcsample_t switchingThresholdLow = 0, switchingThresholdHigh = 0;
static efitick_t minDeltaTimeForStableAdcDetectionNt = 0;
static efitick_t stampCorrectionForAdc = 0;
static int switchingCnt = 0, switchingTeethCnt = 0;
static int prevValue = 0; // not set
static efitick_t prevStamp = 0;
// we need to distinguish between weak and strong signals because of different SNR and thresholds.
static bool isSignalWeak = true;
static int zeroThreshold = 0;
// the 'center' of the signal is variable, so we need to adjust the thresholds.
static int minDeltaThresholdWeakSignal = 0, minDeltaThresholdStrongSignal = 0;
// this is the number of measurements while we store the counter before we reset to 'isSignalWeak'
static int minDeltaThresholdCntPos = 0, minDeltaThresholdCntNeg = 0;
static int integralSum = 0;
static int transitionCooldownCnt = 0;
// hardware-dependent part
#if (EFI_SHAFT_POSITION_INPUT && HAL_TRIGGER_USE_ADC && HAL_USE_ADC) || defined(__DOXYGEN__)
#include "digital_input_exti.h"
//!!!!!!!!!!
#define TRIGGER_ADC_DEBUG_LED TRUE
#ifdef TRIGGER_ADC_DEBUG_LED
#define TRIGGER_ADC_DEBUG_LED1_PORT GPIOH
#define TRIGGER_ADC_DEBUG_LED1_PIN 9
//#define DEBUG_OUTPUT_IGN1
void toggleLed(int led, int mode) {
#if 1
static uint8_t st[5] = { 0 };
if ((st[led] == 0 && mode == 0) || mode == 1) {
palClearPad(TRIGGER_ADC_DEBUG_LED1_PORT, TRIGGER_ADC_DEBUG_LED1_PIN);
#ifdef DEBUG_OUTPUT_IGN1
palClearPad(GPIOI, 8);
#endif
}
else if ((st[led] != 0 && mode == 0) || mode == -1) {
palSetPad(TRIGGER_ADC_DEBUG_LED1_PORT, TRIGGER_ADC_DEBUG_LED1_PIN);
#ifdef DEBUG_OUTPUT_IGN1
palSetPad(GPIOI, 8);
#endif
}
st[led] = (st[led] + 1) % 2/*10*/; //!!!!!!!!!!!
#endif
}
#endif /* TRIGGER_ADC_DEBUG_LED */
// used for fast pin mode switching between ADC and EXTINT
static ioportid_t triggerInputPort;
static ioportmask_t triggerInputPin;
#ifndef PAL_MODE_EXTINT
#define PAL_MODE_EXTINT PAL_MODE_INPUT
#endif /* PAL_MODE_EXTINT */
#if 0
// We want to interpolate between min and max depending on the signal level (adaptive hysteresis).
// But we don't want to measure the signal amplitude directly, so we estimate it by measuring the signal frequency:
// for VR sensors, the amplitude is inversely proportional to the tooth's 'time-width'.
// We find it by dividing the total time by the teeth count, and use the reciprocal value as signal frequency!
static void setHysteresis(int sign) {
// update the hysteresis threshold, but not for every tooth
#ifdef EFI_TRIGGER_COMP_ADAPTIVE_HYSTERESIS
if (toothCnt++ > hystUpdatePeriodNumEvents) {
efitick_t nowNt = getTimeNowNt();
curVrFreqNt = (float)toothCnt / (float)(nowNt - prevNt);
dacHysteresisDelta = (int)efiRound(interpolateClamped(0.0f, dacHysteresisMin, saturatedVrFreqNt, dacHysteresisMax, curVrFreqNt), 1.0f);
toothCnt = 0;
prevNt = nowNt;
#ifdef TRIGGER_COMP_EXTREME_LOGGING
efiPrintf("* f=%f d=%d", curVrFreqNt * 1000.0f, dacHysteresisDelta);
#endif /* TRIGGER_COMP_EXTREME_LOGGING */
}
#endif /* EFI_TRIGGER_COMP_ADAPTIVE_HYSTERESIS */
//comp_lld_set_dac_value(comp, centeredDacValue + dacHysteresisDelta * sign);
}
#endif
static void setTriggerAdcMode(triggerAdcMode_t adcMode) {
void setTriggerAdcMode(triggerAdcMode_t adcMode) {
palSetPadMode(triggerInputPort, triggerInputPin,
(adcMode == TRIGGER_ADC) ? PAL_MODE_INPUT_ANALOG : PAL_MODE_ALTERNATE(PAL_MODE_ALTERNATIVE_EXTINT));
curAdcMode = adcMode;
(adcMode == TRIGGER_ADC_ADC) ? PAL_MODE_INPUT_ANALOG : PAL_MODE_EXTINT);
trigAdcState.curAdcMode = adcMode;
}
static void onTriggerChanged(efitick_t stamp, bool isPrimary, bool isRising) {
//!!!!!!!!!
palWritePad(BOARD_MOD1_PORT, BOARD_MOD1_PIN, isRising ? 1 : 0);
//toggleLed(2, (curAdcMode == TRIGGER_ADC) ? 0 : -1);
//toggleLed(3, (curAdcMode == TRIGGER_EXTI) ? 0 : -1);
#if 1
// todo: support for 3rd trigger input channel
// todo: start using real event time from HW event, not just software timer?
// call the main trigger handler
hwHandleShaftSignal(isPrimary ? 0 : 1, isRising, stamp);
#endif
}
static void shaft_callback(void *arg, efitick_t stamp) {
if (curAdcMode != TRIGGER_EXTI) {
return;
}
static void shaft_callback(void *arg) {
// do the time sensitive things as early as possible!
ioline_t pal_line = (ioline_t)arg;
bool rise = (palReadLine(pal_line) == PAL_HIGH);
onTriggerChanged(stamp, true, rise);
if ((stamp - prevStamp) > minDeltaTimeForStableAdcDetectionNt) {
switchingCnt++;
} else {
switchingCnt = 0;
switchingTeethCnt = 0;
}
if (switchingCnt > 4) {
switchingCnt = 0;
// we need at least 3 wide teeth to be certain!
// we don't want to confuse them with a sync.gap
if (switchingTeethCnt++ > 3) {
switchingTeethCnt = 0;
prevValue = rise ? 1: -1;
setTriggerAdcMode(TRIGGER_ADC);
}
}
prevStamp = stamp;
trigAdcState.digitalCallback(stamp, true, rise);
}
static void cam_callback(void *, efitick_t) {
static void cam_callback(void *) {
// TODO: implement...
}
// todo: add cam support?
#if 0
static void comp_cam_callback(COMPDriver *comp) {
void triggerAdcCallback(triggerAdcSample_t value) {
efitick_t stamp = getTimeNowNt();
if (isRising) {
hwHandleVvtCamSignal(TV_RISE, stamp);
} else {
hwHandleVvtCamSignal(TV_FALL, stamp);
}
}
#endif
void turnOnTriggerInputPins() {
applyNewTriggerInputPins();
trigAdcState.analogCallback(stamp, value);
}
#if 0
static int getDacValue(uint8_t voltage) {
constexpr float maxDacValue = 255.0f; // 8-bit DAC
return (int)efiRound(maxDacValue * (float)voltage * VOLTAGE_1_BYTE_PACKING_DIV / engineConfiguration->adcVcc, 1.0f);
}
#endif
static void resetTriggerDetector() {
// todo: move some of these to config
// we need to make at least minNumAdcMeasurementsPerTooth for 1 tooth (i.e. between two consequent events)
const int minNumAdcMeasurementsPerTooth = 20;
minDeltaTimeForStableAdcDetectionNt = US2NT(US_PER_SECOND_LL * minNumAdcMeasurementsPerTooth * GPT_PERIOD_FAST / GPT_FREQ_FAST);
// we assume that the transition occurs somewhere in the middle of the measurement period, so we take the half of it
stampCorrectionForAdc = US2NT(US_PER_SECOND_LL * GPT_PERIOD_FAST / GPT_FREQ_FAST / 2);
// these thresholds allow to switch from ADC mode to EXTI mode, indicating the clamping of the signal
switchingThresholdLow = voltsToAdc(1.0f);
switchingThresholdHigh = voltsToAdc(4.0f);
switchingCnt = 0;
switchingTeethCnt = 0;
// used to filter out low signals
minDeltaThresholdWeakSignal = voltsToAdc(0.05f); // 50mV
// we need to shift the default threshold even for strong signals because of the possible loss of the first tooth (after the sync)
minDeltaThresholdStrongSignal = voltsToAdc(0.04f); // 5mV
// when the strong signal becomes weak, we want to ignore the increased noise
// so we create a dead-zone between the pos. and neg. thresholds
zeroThreshold = minDeltaThresholdWeakSignal / 2;
triggerAdcITerm = triggerAdcITermMin;
adcThreshold = adcDefaultThreshold;
isSignalWeak = true;
integralSum = 0;
transitionCooldownCnt = 0;
prevValue = 0; // not set
prevStamp = 0;
minDeltaThresholdCntPos = 0;
minDeltaThresholdCntNeg = 0;
}
static int turnOnTriggerInputPin(const char *msg, int index, bool isTriggerShaft) {
brain_pin_e brainPin = isTriggerShaft ?
@ -211,24 +89,8 @@ static int turnOnTriggerInputPin(const char *msg, int index, bool isTriggerShaft
if (!isBrainPinValid(brainPin))
return 0;
#if 0
centeredDacValue = getDacValue(engineConfiguration->triggerCompCenterVolt); // usually 2.5V resistor divider
dacHysteresisMin = getDacValue(engineConfiguration->triggerCompHystMin); // usually ~20mV
dacHysteresisMax = getDacValue(engineConfiguration->triggerCompHystMax); // usually ~300mV
dacHysteresisDelta = dacHysteresisMin;
// 20 rpm (60_2) = 1000*60/((2*60)*20) = 25 ms for 1 tooth event
float satRpm = engineConfiguration->triggerCompSensorSatRpm * RPM_1_BYTE_PACKING_MULT;
hystUpdatePeriodNumEvents = engine->triggerCentral.triggerShape.getSize(); // = 116 for "60-2" trigger wheel
float saturatedToothDurationUs = 60.0f * US_PER_SECOND_F / satRpm / hystUpdatePeriodNumEvents;
saturatedVrFreqNt = 1.0f / US2NT(saturatedToothDurationUs);
efiPrintf("startTIPins(): cDac=%d hystMin=%d hystMax=%d satRpm=%.0f satFreq*1k=%f period=%d",
centeredDacValue, dacHysteresisMin, dacHysteresisMax, satRpm, saturatedVrFreqNt * 1000.0f, hystUpdatePeriodNumEvents);
#endif
resetTriggerDetector();
trigAdcState.init(PASS_ENGINE_PARAMETER_SIGNATURE);
triggerInputPort = getHwPort("trg", brainPin);
triggerInputPin = getHwPin("trg", brainPin);
@ -239,34 +101,23 @@ static int turnOnTriggerInputPin(const char *msg, int index, bool isTriggerShaft
efiExtiEnablePin(msg, brainPin, PAL_EVENT_MODE_BOTH_EDGES, isTriggerShaft ? shaft_callback : cam_callback, (void *)pal_line);
// ADC mode is default, because we don't know if the wheel is already spinning
setTriggerAdcMode(TRIGGER_ADC);
setTriggerAdcMode(TRIGGER_ADC_ADC);
#ifdef TRIGGER_ADC_DEBUG_LED
palSetPadMode(TRIGGER_ADC_DEBUG_LED1_PORT, TRIGGER_ADC_DEBUG_LED1_PIN, PAL_MODE_OUTPUT_PUSHPULL);
#ifdef DEBUG_OUTPUT_IGN1
palSetPadMode(GPIOI, 8, PAL_MODE_OUTPUT_PUSHPULL);
#endif
#endif /* TRIGGER_ADC_DEBUG_LED */
return 0;
}
void startTriggerInputPins(void) {
for (int i = 0; i < TRIGGER_SUPPORTED_CHANNELS; i++) {
if (isConfigurationChanged(triggerInputPins[i])) {
const char * msg = (i == 0 ? "trigger#1" : (i == 1 ? "trigger#2" : "trigger#3"));
turnOnTriggerInputPin(msg, i, true);
}
}
void adcTriggerTurnOffInputPin(brain_pin_e brainPin) {
efiExtiDisablePin(brainPin);
}
void stopTriggerInputPins(void) {
efiPrintf("stopTIPins();");
#if 0
for (int i = 0; i < TRIGGER_SUPPORTED_CHANNELS; i++) {
if (isConfigurationChanged(bc.triggerInputPins[i])) {
turnOffTriggerInputPin(activeConfiguration.bc.triggerInputPins[i]);
}
}
if (isConfigurationChanged(camInput)) {
turnOffTriggerInputPin(activeConfiguration.camInput);
}
#endif
void adcTriggerTurnOnInputPins() {
}
adc_channel_e getAdcChannelForTrigger(void) {
@ -284,12 +135,100 @@ void addAdcChannelForTrigger(void) {
}
}
void triggerAdcCallback(adcsample_t value) {
if (curAdcMode != TRIGGER_ADC) {
void onTriggerChanged(efitick_t stamp, bool isPrimary, bool isRising) {
#ifdef TRIGGER_ADC_DEBUG_LED
toggleLed(0, 0);
#endif /* TRIGGER_ADC_DEBUG_LED */
#if 1
// todo: support for 3rd trigger input channel
// todo: start using real event time from HW event, not just software timer?
// call the main trigger handler
hwHandleShaftSignal(isPrimary ? 0 : 1, isRising, stamp);
#endif
}
#endif /* EFI_SHAFT_POSITION_INPUT && HAL_TRIGGER_USE_ADC && HAL_USE_ADC */
void TriggerAdcDetector::init() {
// todo: move some of these to config
// we need to make at least minNumAdcMeasurementsPerTooth for 1 tooth (i.e. between two consequent events)
const int minNumAdcMeasurementsPerTooth = 20;
minDeltaTimeForStableAdcDetectionNt = US2NT(US_PER_SECOND_LL * minNumAdcMeasurementsPerTooth * GPT_PERIOD_FAST / GPT_FREQ_FAST);
// we assume that the transition occurs somewhere in the middle of the measurement period, so we take the half of it
stampCorrectionForAdc = US2NT(US_PER_SECOND_LL * GPT_PERIOD_FAST / GPT_FREQ_FAST / 2);
// these thresholds allow to switch from ADC mode to EXTI mode, indicating the clamping of the signal
switchingThresholdLow = voltsToAdcDivided(1.0f);
switchingThresholdHigh = voltsToAdcDivided(4.0f);
// used to filter out low signals
minDeltaThresholdWeakSignal = voltsToAdcDivided(0.05f); // 50mV
// we need to shift the default threshold even for strong signals because of the possible loss of the first tooth (after the sync)
minDeltaThresholdStrongSignal = voltsToAdcDivided(0.04f); // 5mV
const triggerAdcSample_t adcDeltaThreshold = voltsToAdcDivided(0.25f);
adcDefaultThreshold = voltsToAdcDivided(3.4f); // this corresponds to VREF1 on Hellen boards
adcMinThreshold = adcDefaultThreshold - adcDeltaThreshold;
adcMaxThreshold = adcDefaultThreshold - adcDeltaThreshold;
reset();
}
void TriggerAdcDetector::reset() {
switchingCnt = 0;
switchingTeethCnt = 0;
// when the strong signal becomes weak, we want to ignore the increased noise
// so we create a dead-zone between the pos. and neg. thresholds
zeroThreshold = minDeltaThresholdWeakSignal / 2;
triggerAdcITerm = triggerAdcITermMin;
adcThreshold = adcDefaultThreshold;
isSignalWeak = true;
integralSum = 0;
transitionCooldownCnt = 0;
prevValue = 0; // not set
prevStamp = 0;
minDeltaThresholdCntPos = 0;
minDeltaThresholdCntNeg = 0;
}
void TriggerAdcDetector::digitalCallback(efitick_t stamp, bool isPrimary, bool rise) {
if (curAdcMode != TRIGGER_ADC_EXTI) {
return;
}
efitick_t stamp = getTimeNowNt();
onTriggerChanged(stamp, isPrimary, rise);
if ((stamp - prevStamp) > minDeltaTimeForStableAdcDetectionNt) {
switchingCnt++;
} else {
switchingCnt = 0;
switchingTeethCnt = 0;
}
if (switchingCnt > 4) {
switchingCnt = 0;
// we need at least 3 wide teeth to be certain!
// we don't want to confuse them with a sync.gap
if (switchingTeethCnt++ > 3) {
switchingTeethCnt = 0;
prevValue = rise ? 1: -1;
setTriggerAdcMode(TRIGGER_ADC_ADC);
}
}
prevStamp = stamp;
}
void TriggerAdcDetector::analogCallback(efitick_t stamp, triggerAdcSample_t value) {
if (curAdcMode != TRIGGER_ADC_ADC) {
return;
}
// <1V or >4V?
if (value >= switchingThresholdHigh || value <= switchingThresholdLow) {
@ -324,7 +263,7 @@ void triggerAdcCallback(adcsample_t value) {
// we haven't seen the strong signal (pos or neg) for too long, maybe it's lost or too weak?
if (minDeltaThresholdCntPos <= 0 || minDeltaThresholdCntNeg <= 0) {
// reset to the weak signal mode
resetTriggerDetector();
reset();
return;
}
}
@ -362,17 +301,9 @@ void triggerAdcCallback(adcsample_t value) {
transition = -1;
}
else {
//!!!!!!!!!!
//toggleLed(2, 0);
return; // both are positive/negative/zero: not interested!
}
//!!!!!!!!!!
//toggleLed(2, -1);
//!!!!!!!!!!
//toggleLed(3, 0);
if (isSignalWeak) {
if (minDeltaThresholdCntPos >= DELTA_THRESHOLD_CNT_LOW && minDeltaThresholdCntNeg >= DELTA_THRESHOLD_CNT_LOW) {
// ok, now we have a legit strong signal, let's restore the threshold
@ -407,7 +338,7 @@ void triggerAdcCallback(adcsample_t value) {
// we need at least 3 high-signal teeth to be certain!
if (switchingTeethCnt++ > 3) {
switchingTeethCnt = 0;
setTriggerAdcMode(TRIGGER_EXTI);
setTriggerAdcMode(TRIGGER_ADC_EXTI);
// we don't want to loose the signal on return
minDeltaThresholdCntPos = DELTA_THRESHOLD_CNT_HIGH;
minDeltaThresholdCntNeg = DELTA_THRESHOLD_CNT_HIGH;
@ -422,7 +353,5 @@ void triggerAdcCallback(adcsample_t value) {
prevValue = transition;
prevStamp = stamp;
}
#endif /* EFI_SHAFT_POSITION_INPUT && HAL_TRIGGER_USE_ADC && HAL_USE_ADC */

View File

@ -0,0 +1,60 @@
/**
* @file trigger_input_adc.h
* @brief Position sensor hardware layer, Using ADC and software comparator
*
* @date Jan 27, 2020
* @author andreika <prometheus.pcb@gmail.com>
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#pragma once
#include "global.h"
#include "trigger_input.h"
#include "adc_inputs.h"
#define DELTA_THRESHOLD_CNT_LOW (GPT_FREQ_FAST / GPT_PERIOD_FAST / 32) // ~1/32 second?
#define DELTA_THRESHOLD_CNT_HIGH (GPT_FREQ_FAST / GPT_PERIOD_FAST / 4) // ~1/4 second?
class TriggerAdcDetector {
public:
void init();
void reset();
void digitalCallback(efitick_t stamp, bool isPrimary, bool rise);
void analogCallback(efitick_t stamp, triggerAdcSample_t value);
public:
triggerAdcSample_t adcDefaultThreshold;
triggerAdcSample_t adcMinThreshold;
triggerAdcSample_t adcMaxThreshold;
float triggerAdcITermCoef = 1600.0f;
float triggerAdcITermMin = 3.125e-8f; // corresponds to rpm=25
int transitionCooldown = 5;
triggerAdcMode_t curAdcMode = TRIGGER_ADC_NONE;
float adcThreshold = adcDefaultThreshold;
float triggerAdcITerm = triggerAdcITermMin;
// these thresholds allow to switch from ADC mode (low-rpm) to EXTI mode (fast-rpm), indicating the clamping of the signal
triggerAdcSample_t switchingThresholdLow = 0, switchingThresholdHigh = 0;
efitick_t minDeltaTimeForStableAdcDetectionNt = 0;
efitick_t stampCorrectionForAdc = 0;
int switchingCnt = 0, switchingTeethCnt = 0;
int prevValue = 0; // not set
efitick_t prevStamp = 0;
// we need to distinguish between weak and strong signals because of different SNR and thresholds.
bool isSignalWeak = true;
int zeroThreshold = 0;
// the 'center' of the signal is variable, so we need to adjust the thresholds.
int minDeltaThresholdWeakSignal = 0, minDeltaThresholdStrongSignal = 0;
// this is the number of measurements while we store the counter before we reset to 'isSignalWeak'
int minDeltaThresholdCntPos = 0, minDeltaThresholdCntNeg = 0;
int integralSum = 0;
int transitionCooldownCnt = 0;
};

View File

@ -20,6 +20,7 @@ HW_LAYER_EMS_CPP = \
$(PROJECT_DIR)/hw_layer/digital_input/trigger/trigger_input.cpp \
$(PROJECT_DIR)/hw_layer/digital_input/trigger/trigger_input_icu.cpp \
$(PROJECT_DIR)/hw_layer/digital_input/trigger/trigger_input_exti.cpp \
$(PROJECT_DIR)/hw_layer/digital_input/trigger/trigger_input_adc.cpp \
$(PROJECT_DIR)/hw_layer/hardware.cpp \
$(PROJECT_DIR)/hw_layer/smart_gpio.cpp \
$(PROJECT_DIR)/hw_layer/mmc_card.cpp \