2017-03-24 10:41:36 -07:00
/**
* @ file adc_inputs . cpp
* @ brief Low level ADC code
*
2019-05-15 01:16:41 -07:00
* rusEfi uses two ADC devices on the same 16 pins at the moment . Two ADC devices are used in orde to distinguish between
* fast and slow devices . The idea is that but only having few channels in ' fast ' mode we can sample those faster ?
*
* At the moment rusEfi does not allow to have more than 16 ADC channels combined . At the moment there is no flexibility to use
2019-05-28 15:19:51 -07:00
* any ADC pins , only the hardcoded choice of 16 pins .
2019-05-15 01:16:41 -07:00
*
2017-03-24 10:41:36 -07:00
* Slow ADC group is used for IAT , CLT , AFR , VBATT etc - this one is currently sampled at 20 Hz
*
2018-04-08 08:35:24 -07:00
* Fast ADC group is used for TPS , MAP , MAF HIP - this one is currently sampled at 10 KHz
2018-04-08 08:38:14 -07:00
* We need frequent MAP for map_averaging . cpp
2019-04-24 17:51:14 -07:00
* We need frequent TPS for better TPS / TPS enrichment and better ETB control
2017-03-24 10:41:36 -07:00
*
2018-12-23 20:29:19 -08:00
* 10 KHz equals one measurement every 3.6 degrees at 6000 RPM
*
2017-03-24 10:41:36 -07:00
* @ date Jan 14 , 2013
2020-01-13 18:57:43 -08:00
* @ author Andrey Belomutskiy , ( c ) 2012 - 2020
2017-03-24 10:41:36 -07:00
*/
2018-09-16 19:26:57 -07:00
# include "global.h"
2017-03-24 10:41:36 -07:00
2019-04-12 17:52:51 -07:00
# if HAL_USE_ADC
2019-07-04 00:57:21 -07:00
# include "os_access.h"
2017-03-24 10:41:36 -07:00
# include "engine.h"
# include "adc_inputs.h"
2019-09-21 11:33:38 -07:00
# include "adc_subscription.h"
2017-03-24 10:41:36 -07:00
# include "AdcConfiguration.h"
# include "mpu_util.h"
2019-12-11 06:28:11 -08:00
# include "periodic_thread_controller.h"
2017-03-24 10:41:36 -07:00
# include "pin_repository.h"
# include "engine_math.h"
# include "engine_controller.h"
# include "maf.h"
2019-10-11 17:43:21 -07:00
# include "perf_trace.h"
2017-03-24 10:41:36 -07:00
/* Depth of the conversion buffer, channels are sampled X times each.*/
# define ADC_BUF_DEPTH_SLOW 8
# define ADC_BUF_DEPTH_FAST 4
static adc_channel_mode_e adcHwChannelEnabled [ HW_MAX_ADC_INDEX ] ;
static const char * adcHwChannelUsage [ HW_MAX_ADC_INDEX ] ;
2019-09-22 06:56:06 -07:00
EXTERN_ENGINE ;
// Board voltage, with divider coefficient accounted for
float getVoltageDivided ( const char * msg , adc_channel_e hwChannel DECLARE_ENGINE_PARAMETER_SUFFIX ) {
2019-09-22 07:02:07 -07:00
return getVoltage ( msg , hwChannel PASS_ENGINE_PARAMETER_SUFFIX ) * engineConfiguration - > analogInputDividerCoefficient ;
2019-09-22 06:56:06 -07:00
}
2019-09-22 13:41:10 -07:00
// voltage in MCU universe, from zero to VDD
float getVoltage ( const char * msg , adc_channel_e hwChannel DECLARE_ENGINE_PARAMETER_SUFFIX ) {
return adcToVolts ( getAdcValue ( msg , hwChannel ) ) ;
}
2017-03-24 10:41:36 -07:00
AdcDevice : : AdcDevice ( ADCConversionGroup * hwConfig ) {
this - > hwConfig = hwConfig ;
channelCount = 0 ;
conversionCount = 0 ;
errorsCount = 0 ;
hwConfig - > sqr1 = 0 ;
hwConfig - > sqr2 = 0 ;
hwConfig - > sqr3 = 0 ;
memset ( hardwareIndexByIndernalAdcIndex , 0 , sizeof ( hardwareIndexByIndernalAdcIndex ) ) ;
memset ( internalAdcIndexByHardwareIndex , 0xFFFFFFFF , sizeof ( internalAdcIndexByHardwareIndex ) ) ;
}
2019-03-28 19:46:10 -07:00
# if !defined(PWM_FREQ_FAST) || !defined(PWM_PERIOD_FAST)
2017-03-24 10:41:36 -07:00
/**
* 8000 RPM is 133 Hz
* If we want to sample MAP once per 5 degrees we need 133 Hz * ( 360 / 5 ) = 9576 Hz of fast ADC
*/
// todo: migrate to continues ADC mode? probably not - we cannot afford the callback in
// todo: continues mode. todo: look into our options
# define PWM_FREQ_FAST 100000 /* PWM clock frequency. I wonder what does this setting mean? */
# define PWM_PERIOD_FAST 10 /* PWM period (in PWM ticks). */
2019-03-28 19:46:10 -07:00
# endif /* PWM_FREQ_FAST PWM_PERIOD_FAST */
2017-03-24 10:41:36 -07:00
2019-05-14 13:38:14 -07:00
// is there a reason to have this configurable at runtime?
2019-03-28 19:46:10 -07:00
# ifndef ADC_SLOW_DEVICE
2017-03-24 10:41:36 -07:00
# define ADC_SLOW_DEVICE ADCD1
2019-03-28 19:46:10 -07:00
# endif /* ADC_SLOW_DEVICE */
2017-03-24 10:41:36 -07:00
2019-05-14 13:38:14 -07:00
// is there a reason to have this configurable at runtime?
2019-03-28 19:46:10 -07:00
# ifndef ADC_FAST_DEVICE
2017-03-24 10:41:36 -07:00
# define ADC_FAST_DEVICE ADCD2
2019-03-28 19:46:10 -07:00
# endif /* ADC_FAST_DEVICE */
2017-03-24 10:41:36 -07:00
2017-08-07 04:28:21 -07:00
static volatile int slowAdcCounter = 0 ;
2017-03-24 10:41:36 -07:00
static LoggingWithStorage logger ( " ADC " ) ;
// todo: move this flag to Engine god object
static int adcDebugReporting = false ;
EXTERN_ENGINE ;
static adcsample_t getAvgAdcValue ( int index , adcsample_t * samples , int bufDepth , int numChannels ) {
2019-12-11 06:28:11 -08:00
uint32_t result = 0 ;
2017-03-24 10:41:36 -07:00
for ( int i = 0 ; i < bufDepth ; i + + ) {
result + = samples [ index ] ;
index + = numChannels ;
}
2019-12-11 06:28:11 -08:00
// this truncation is guaranteed to not be lossy - the average can't be larger than adcsample_t
return static_cast < adcsample_t > ( result / bufDepth ) ;
2017-03-24 10:41:36 -07:00
}
2019-10-19 05:01:28 -07:00
// See https://github.com/rusefi/rusefi/issues/976 for discussion on these values
# define ADC_SAMPLING_SLOW ADC_SAMPLE_56
2017-03-24 10:41:36 -07:00
# define ADC_SAMPLING_FAST ADC_SAMPLE_28
/*
* ADC conversion group .
*/
2019-12-11 06:28:11 -08:00
static ADCConversionGroup adcgrpcfgSlow = { FALSE , 0 , nullptr , NULL ,
2017-03-24 10:41:36 -07:00
/* HW dependent part.*/
ADC_TwoSamplingDelay_20Cycles , // cr1
ADC_CR2_SWSTART , // cr2
2017-05-01 04:39:32 -07:00
/**
* here we configure all possible channels for slow mode . Some channels would not actually
* be used hopefully that ' s fine to configure all possible channels .
*/
2017-03-24 10:41:36 -07:00
ADC_SMPR1_SMP_AN10 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR1_SMP_AN11 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR1_SMP_AN12 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR1_SMP_AN13 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR1_SMP_AN14 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR1_SMP_AN15 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR1_SMP_SENSOR ( ADC_SAMPLE_144 )
, // sample times for channels 10...18
ADC_SMPR2_SMP_AN0 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR2_SMP_AN1 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR2_SMP_AN2 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR2_SMP_AN3 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR2_SMP_AN4 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR2_SMP_AN5 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR2_SMP_AN6 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR2_SMP_AN7 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR2_SMP_AN8 ( ADC_SAMPLING_SLOW ) |
ADC_SMPR2_SMP_AN9 ( ADC_SAMPLING_SLOW )
, // In this field must be specified the sample times for channels 0...9
2019-04-14 15:09:58 -07:00
0 ,
0 ,
2017-03-24 10:41:36 -07:00
0 , // Conversion group sequence 13...16 + sequence length
0 , // Conversion group sequence 7...12
0 // Conversion group sequence 1...6
} ;
AdcDevice slowAdc ( & adcgrpcfgSlow ) ;
2019-07-05 17:34:41 -07:00
void adc_callback_fast ( ADCDriver * adcp , adcsample_t * buffer , size_t n ) ;
2017-03-24 10:41:36 -07:00
static ADCConversionGroup adcgrpcfg_fast = { FALSE , 0 /* num_channels */ , adc_callback_fast , NULL ,
/* HW dependent part.*/
ADC_TwoSamplingDelay_5Cycles , // cr1
ADC_CR2_SWSTART , // cr2
2017-05-01 04:39:32 -07:00
/**
* here we configure all possible channels for fast mode . Some channels would not actually
* be used hopefully that ' s fine to configure all possible channels .
*
*/
ADC_SMPR1_SMP_AN10 ( ADC_SAMPLING_FAST ) |
ADC_SMPR1_SMP_AN11 ( ADC_SAMPLING_FAST ) |
ADC_SMPR1_SMP_AN12 ( ADC_SAMPLING_FAST ) |
ADC_SMPR1_SMP_AN13 ( ADC_SAMPLING_FAST ) |
ADC_SMPR1_SMP_AN14 ( ADC_SAMPLING_FAST ) |
ADC_SMPR1_SMP_AN15 ( ADC_SAMPLING_FAST )
, // sample times for channels 10...18
ADC_SMPR2_SMP_AN0 ( ADC_SAMPLING_FAST ) |
ADC_SMPR2_SMP_AN1 ( ADC_SAMPLING_FAST ) |
ADC_SMPR2_SMP_AN2 ( ADC_SAMPLING_FAST ) |
ADC_SMPR2_SMP_AN3 ( ADC_SAMPLING_FAST ) |
ADC_SMPR2_SMP_AN4 ( ADC_SAMPLING_FAST ) |
ADC_SMPR2_SMP_AN5 ( ADC_SAMPLING_FAST ) |
ADC_SMPR2_SMP_AN6 ( ADC_SAMPLING_FAST ) |
ADC_SMPR2_SMP_AN7 ( ADC_SAMPLING_FAST ) |
ADC_SMPR2_SMP_AN8 ( ADC_SAMPLING_FAST ) |
ADC_SMPR2_SMP_AN9 ( ADC_SAMPLING_FAST ) , // In this field must be specified the sample times for channels 0...9
2017-03-24 10:41:36 -07:00
2019-04-14 15:09:58 -07:00
0 ,
0 ,
2017-03-24 10:41:36 -07:00
0 , // Conversion group sequence 13...16 + sequence length
0 , // Conversion group sequence 7...12
0
// Conversion group sequence 1...6
} ;
AdcDevice fastAdc ( & adcgrpcfg_fast ) ;
2019-04-12 17:52:51 -07:00
# if HAL_USE_PWM
2017-03-24 10:41:36 -07:00
static void pwmpcb_fast ( PWMDriver * pwmp ) {
2019-02-23 09:33:49 -08:00
efiAssertVoid ( CUSTOM_ERR_6659 , getCurrentRemainingStack ( ) > 32 , " lwStAdcFast " ) ;
2019-04-12 17:52:51 -07:00
# if EFI_INTERNAL_ADC
2017-03-24 10:41:36 -07:00
( void ) pwmp ;
/*
* Starts an asynchronous ADC conversion operation , the conversion
* will be executed in parallel to the current PWM cycle and will
* terminate before the next PWM cycle .
*/
2017-03-30 06:01:28 -07:00
chSysLockFromISR ( )
2017-03-24 10:41:36 -07:00
;
if ( ADC_FAST_DEVICE . state ! = ADC_READY & &
ADC_FAST_DEVICE . state ! = ADC_COMPLETE & &
ADC_FAST_DEVICE . state ! = ADC_ERROR ) {
fastAdc . errorsCount + + ;
// todo: when? why? firmwareError(OBD_PCM_Processor_Fault, "ADC fast not ready?");
2017-03-30 06:01:28 -07:00
chSysUnlockFromISR ( )
2017-03-24 10:41:36 -07:00
;
return ;
}
2019-10-11 17:43:21 -07:00
2017-03-24 10:41:36 -07:00
adcStartConversionI ( & ADC_FAST_DEVICE , & adcgrpcfg_fast , fastAdc . samples , ADC_BUF_DEPTH_FAST ) ;
2017-03-30 06:01:28 -07:00
chSysUnlockFromISR ( )
2017-03-24 10:41:36 -07:00
;
fastAdc . conversionCount + + ;
2017-11-27 18:49:58 -08:00
# endif /* EFI_INTERNAL_ADC */
2017-03-24 10:41:36 -07:00
}
2018-11-16 04:40:06 -08:00
# endif /* HAL_USE_PWM */
2017-03-24 10:41:36 -07:00
float getMCUInternalTemperature ( void ) {
2019-04-12 17:52:51 -07:00
# if defined(ADC_CHANNEL_SENSOR)
2017-03-24 10:41:36 -07:00
float TemperatureValue = adcToVolts ( slowAdc . getAdcValueByHwChannel ( ADC_CHANNEL_SENSOR ) ) ;
2019-06-23 06:21:12 -07:00
TemperatureValue - = 0.760 ; // Subtract the reference voltage at 25 deg C
2017-03-24 10:41:36 -07:00
TemperatureValue / = .0025 ; // Divide by slope 2.5mV
2019-06-23 06:21:12 -07:00
TemperatureValue + = 25.0 ; // Add the 25 deg C
2017-03-24 10:41:36 -07:00
return TemperatureValue ;
2019-03-28 19:46:10 -07:00
# else
return 0 ;
# endif /* ADC_CHANNEL_SENSOR */
2017-03-24 10:41:36 -07:00
}
int getInternalAdcValue ( const char * msg , adc_channel_e hwChannel ) {
if ( hwChannel = = EFI_ADC_NONE ) {
2017-04-12 04:57:52 -07:00
warning ( CUSTOM_OBD_ANALOG_INPUT_NOT_CONFIGURED , " ADC: %s input is not configured " , msg ) ;
2017-03-24 10:41:36 -07:00
return - 1 ;
}
2017-11-27 18:49:58 -08:00
# if EFI_ENABLE_MOCK_ADC
2017-03-24 10:41:36 -07:00
if ( engine - > engineState . mockAdcState . hasMockAdc [ hwChannel ] )
return engine - > engineState . mockAdcState . getMockAdcValue ( hwChannel ) ;
2017-11-27 18:49:58 -08:00
# endif /* EFI_ENABLE_MOCK_ADC */
2017-03-24 10:41:36 -07:00
if ( adcHwChannelEnabled [ hwChannel ] = = ADC_FAST ) {
int internalIndex = fastAdc . internalAdcIndexByHardwareIndex [ hwChannel ] ;
// todo if ADC_BUF_DEPTH_FAST EQ 1
// return fastAdc.samples[internalIndex];
int value = getAvgAdcValue ( internalIndex , fastAdc . samples , ADC_BUF_DEPTH_FAST , fastAdc . size ( ) ) ;
return value ;
}
if ( adcHwChannelEnabled [ hwChannel ] ! = ADC_SLOW ) {
2019-05-10 15:58:05 -07:00
warning ( CUSTOM_OBD_WRONG_ADC_MODE , " ADC is off [%s] index=%d " , msg , hwChannel ) ;
2017-03-24 10:41:36 -07:00
}
return slowAdc . getAdcValueByHwChannel ( hwChannel ) ;
}
2019-04-12 17:52:51 -07:00
# if HAL_USE_PWM
2017-03-24 10:41:36 -07:00
static PWMConfig pwmcfg_fast = { PWM_FREQ_FAST , PWM_PERIOD_FAST , pwmpcb_fast , { {
PWM_OUTPUT_DISABLED , NULL } , { PWM_OUTPUT_DISABLED , NULL } , {
PWM_OUTPUT_DISABLED , NULL } , { PWM_OUTPUT_DISABLED , NULL } } ,
/* HW dependent part.*/
0 , 0 } ;
2018-11-16 04:40:06 -08:00
# endif /* HAL_USE_PWM */
2017-03-24 10:41:36 -07:00
2017-04-21 17:07:17 -07:00
static void initAdcPin ( brain_pin_e pin , const char * msg ) {
2019-03-08 04:01:15 -08:00
UNUSED ( msg ) ;
2017-04-21 17:07:17 -07:00
// todo: migrate to scheduleMsg if we want this back print("adc %s\r\n", msg);
2017-05-15 05:40:54 -07:00
efiSetPadMode ( " adc input " , pin , PAL_MODE_INPUT_ANALOG ) ;
2017-04-21 17:07:17 -07:00
}
2017-03-24 10:41:36 -07:00
const char * getAdcMode ( adc_channel_e hwChannel ) {
if ( slowAdc . isHwUsed ( hwChannel ) ) {
return " slow " ;
}
if ( fastAdc . isHwUsed ( hwChannel ) ) {
return " fast " ;
}
return " INACTIVE - need restart " ;
}
static void initAdcHwChannel ( adc_channel_e hwChannel ) {
2017-04-21 17:07:17 -07:00
brain_pin_e pin = getAdcChannelBrainPin ( " adc " , hwChannel ) ;
2017-03-24 10:41:36 -07:00
2017-04-21 17:09:57 -07:00
initAdcPin ( pin , " hw " ) ;
2017-03-24 10:41:36 -07:00
}
2019-06-08 06:51:36 -07:00
int AdcDevice : : size ( ) const {
2017-03-24 10:41:36 -07:00
return channelCount ;
}
2019-06-08 06:51:36 -07:00
int AdcDevice : : getAdcValueByHwChannel ( int hwChannel ) const {
2017-03-24 10:41:36 -07:00
int internalIndex = internalAdcIndexByHardwareIndex [ hwChannel ] ;
return values . adc_data [ internalIndex ] ;
}
2019-06-08 06:51:36 -07:00
int AdcDevice : : getAdcValueByIndex ( int internalIndex ) const {
2017-03-24 10:41:36 -07:00
return values . adc_data [ internalIndex ] ;
}
2019-06-23 06:21:12 -07:00
void AdcDevice : : invalidateSamplesCache ( ) {
2019-06-23 07:34:49 -07:00
# if defined(STM32F7XX)
2019-06-23 06:21:12 -07:00
// The STM32F7xx has a data cache
// DMA operations DO NOT invalidate cache lines, since the ARM m7 doesn't have
// anything like a CCI that maintains coherency across multiple bus masters.
// As a result, we have to manually invalidate the D-cache any time we (the CPU)
// would like to read something that somebody else wrote (ADC via DMA, in this case)
SCB_InvalidateDCache_by_Addr ( reinterpret_cast < uint32_t * > ( samples ) , sizeof ( samples ) ) ;
2020-03-18 08:37:53 -07:00
# endif /* STM32F7XX */
2019-06-23 06:21:12 -07:00
}
2017-03-24 10:41:36 -07:00
void AdcDevice : : init ( void ) {
hwConfig - > num_channels = size ( ) ;
hwConfig - > sqr1 + = ADC_SQR1_NUM_CH ( size ( ) ) ;
}
2019-06-08 06:51:36 -07:00
bool AdcDevice : : isHwUsed ( adc_channel_e hwChannelIndex ) const {
2017-03-24 10:41:36 -07:00
for ( int i = 0 ; i < channelCount ; i + + ) {
if ( hardwareIndexByIndernalAdcIndex [ i ] = = hwChannelIndex ) {
return true ;
}
}
return false ;
}
void AdcDevice : : enableChannel ( adc_channel_e hwChannel ) {
int logicChannel = channelCount + + ;
internalAdcIndexByHardwareIndex [ hwChannel ] = logicChannel ;
hardwareIndexByIndernalAdcIndex [ logicChannel ] = hwChannel ;
if ( logicChannel < 6 ) {
hwConfig - > sqr3 + = ( hwChannel ) < < ( 5 * logicChannel ) ;
} else if ( logicChannel < 12 ) {
hwConfig - > sqr2 + = ( hwChannel ) < < ( 5 * ( logicChannel - 6 ) ) ;
} else {
hwConfig - > sqr1 + = ( hwChannel ) < < ( 5 * ( logicChannel - 12 ) ) ;
}
// todo: support for more then 12 channels? not sure how needed it would be
}
void AdcDevice : : enableChannelAndPin ( adc_channel_e hwChannel ) {
enableChannel ( hwChannel ) ;
initAdcHwChannel ( hwChannel ) ;
}
2019-03-02 15:41:25 -08:00
static void printAdcValue ( int channel ) {
int value = getAdcValue ( " print " , ( adc_channel_e ) channel ) ;
2017-03-24 10:41:36 -07:00
float volts = adcToVoltsDivided ( value ) ;
2018-01-23 09:05:14 -08:00
scheduleMsg ( & logger , " adc voltage : %.2f " , volts ) ;
2017-03-24 10:41:36 -07:00
}
2019-06-08 06:51:36 -07:00
adc_channel_e AdcDevice : : getAdcHardwareIndexByInternalIndex ( int index ) const {
2017-03-24 10:41:36 -07:00
return hardwareIndexByIndernalAdcIndex [ index ] ;
}
static void printFullAdcReport ( Logging * logger ) {
scheduleMsg ( logger , " fast %d slow %d " , fastAdc . conversionCount , slowAdc . conversionCount ) ;
for ( int index = 0 ; index < slowAdc . size ( ) ; index + + ) {
appendMsgPrefix ( logger ) ;
adc_channel_e hwIndex = slowAdc . getAdcHardwareIndexByInternalIndex ( index ) ;
2019-11-19 15:17:03 -08:00
if ( hwIndex ! = EFI_ADC_NONE & & hwIndex ! = EFI_ADC_ERROR ) {
2017-08-29 07:03:24 -07:00
ioportid_t port = getAdcChannelPort ( " print " , hwIndex ) ;
int pin = getAdcChannelPin ( hwIndex ) ;
2017-03-24 10:41:36 -07:00
2017-08-29 07:03:24 -07:00
int adcValue = slowAdc . getAdcValueByIndex ( index ) ;
appendPrintf ( logger , " ch%d %s%d " , index , portname ( port ) , pin ) ;
appendPrintf ( logger , " ADC%d 12bit=%d " , hwIndex , adcValue ) ;
float volts = adcToVolts ( adcValue ) ;
2018-01-23 09:05:14 -08:00
appendPrintf ( logger , " v=%.2f " , volts ) ;
2017-08-29 07:03:24 -07:00
appendMsgPostfix ( logger ) ;
scheduleLogging ( logger ) ;
}
2017-03-24 10:41:36 -07:00
}
}
static void setAdcDebugReporting ( int value ) {
adcDebugReporting = value ;
scheduleMsg ( & logger , " adcDebug=%d " , adcDebugReporting ) ;
}
2018-01-22 14:45:10 -08:00
void waitForSlowAdc ( int lastAdcCounter ) {
2017-08-07 04:28:21 -07:00
// we use slowAdcCounter instead of slowAdc.conversionCount because we need ADC_COMPLETE state
// todo: use sync.objects?
2018-01-22 14:45:10 -08:00
while ( slowAdcCounter < = lastAdcCounter ) {
2017-08-07 04:28:21 -07:00
chThdSleepMilliseconds ( 1 ) ;
}
}
2018-01-22 14:45:10 -08:00
int getSlowAdcCounter ( ) {
return slowAdcCounter ;
}
2019-10-11 17:43:21 -07:00
2019-12-11 06:28:11 -08:00
class SlowAdcController : public PeriodicController < 256 > {
public :
SlowAdcController ( )
: PeriodicController ( " ADC " , NORMALPRIO + 5 , 200 )
{
}
2019-10-08 17:44:59 -07:00
2019-12-21 18:11:09 -08:00
void PeriodicTask ( efitick_t nowNt ) override {
2019-12-11 06:28:11 -08:00
{
ScopePerf perf ( PE : : AdcConversionSlow ) ;
2019-10-08 17:44:59 -07:00
2019-12-11 06:28:11 -08:00
slowAdc . conversionCount + + ;
msg_t result = adcConvert ( & ADC_SLOW_DEVICE , & adcgrpcfgSlow , slowAdc . samples , ADC_BUF_DEPTH_SLOW ) ;
2017-03-24 10:41:36 -07:00
2019-12-11 06:28:11 -08:00
// If something went wrong - try again later
if ( result = = MSG_RESET | | result = = MSG_TIMEOUT ) {
slowAdc . errorsCount + + ;
return ;
}
2019-12-17 05:34:56 -08:00
# ifdef USE_ADC3_VBATT_HACK
void proteusAdcHack ( ) ;
proteusAdcHack ( ) ;
# endif
2017-03-24 10:41:36 -07:00
}
2019-09-21 11:33:38 -07:00
2019-12-11 06:28:11 -08:00
{
ScopePerf perf ( PE : : AdcProcessSlow ) ;
slowAdc . invalidateSamplesCache ( ) ;
/* Calculates the average values from the ADC samples.*/
for ( int i = 0 ; i < slowAdc . size ( ) ; i + + ) {
adcsample_t value = getAvgAdcValue ( i , slowAdc . samples , ADC_BUF_DEPTH_SLOW , slowAdc . size ( ) ) ;
adcsample_t prev = slowAdc . values . adc_data [ i ] ;
float result = ( slowAdcCounter = = 0 ) ? value :
CONFIG ( slowAdcAlpha ) * value + ( 1 - CONFIG ( slowAdcAlpha ) ) * prev ;
slowAdc . values . adc_data [ i ] = ( adcsample_t ) result ;
}
slowAdcCounter + + ;
2020-02-08 14:48:15 -08:00
AdcSubscription : : UpdateSubscribers ( nowNt ) ;
2019-12-11 06:28:11 -08:00
}
2019-10-08 17:44:59 -07:00
}
2019-12-11 06:28:11 -08:00
} ;
2017-03-24 10:41:36 -07:00
2019-09-22 23:02:42 -07:00
static char errorMsgBuff [ _MAX_FILLER + 2 ] ;
2017-03-24 10:41:36 -07:00
2019-03-28 19:46:10 -07:00
void addChannel ( const char * name , adc_channel_e setting , adc_channel_mode_e mode ) {
2017-03-24 10:41:36 -07:00
if ( setting = = EFI_ADC_NONE ) {
return ;
}
2019-12-02 17:32:21 -08:00
if ( /*type-limited (int)setting < 0 || */ ( int ) setting > = HW_MAX_ADC_INDEX ) {
firmwareError ( CUSTOM_INVALID_ADC , " Invalid ADC setting %s " , name ) ;
return ;
}
2017-03-24 10:41:36 -07:00
if ( adcHwChannelEnabled [ setting ] ! = ADC_OFF ) {
getPinNameByAdcChannel ( name , setting , errorMsgBuff ) ;
2020-03-29 04:27:36 -07:00
firmwareError ( CUSTOM_ERR_ADC_USED , " Analog input error: input \" %s \" selected for %s but was already used by %s " , errorMsgBuff , name , adcHwChannelUsage [ setting ] ) ;
2017-03-24 10:41:36 -07:00
}
adcHwChannelUsage [ setting ] = name ;
adcHwChannelEnabled [ setting ] = mode ;
}
2019-03-28 19:46:10 -07:00
void removeChannel ( const char * name , adc_channel_e setting ) {
2019-04-14 10:19:36 -07:00
( void ) name ;
2019-03-28 19:46:10 -07:00
if ( setting = = EFI_ADC_NONE ) {
return ;
}
adcHwChannelEnabled [ setting ] = ADC_OFF ;
}
2017-03-24 10:41:36 -07:00
static void configureInputs ( void ) {
memset ( adcHwChannelEnabled , 0 , sizeof ( adcHwChannelEnabled ) ) ;
memset ( adcHwChannelUsage , 0 , sizeof ( adcHwChannelUsage ) ) ;
2019-12-03 20:55:18 -08:00
/**
* order of analog channels here is totally random and has no meaning
* we also have some weird implementation with internal indices - that all has no meaning , it ' s just a random implementation
* which does not mean anything .
*/
2017-03-24 10:41:36 -07:00
addChannel ( " MAP " , engineConfiguration - > map . sensor . hwChannel , ADC_FAST ) ;
if ( hasMafSensor ( ) ) {
addChannel ( " MAF " , engineConfiguration - > mafAdcChannel , ADC_FAST ) ;
}
addChannel ( " hip " , engineConfiguration - > hipOutputChannel , ADC_FAST ) ;
2019-04-15 22:55:15 -07:00
addChannel ( " baro " , engineConfiguration - > baroSensor . hwChannel , ADC_SLOW ) ;
2020-03-20 06:53:45 -07:00
addChannel ( " TPS1_1 " , engineConfiguration - > tps1_1AdcChannel , ADC_SLOW ) ;
addChannel ( " TPS1_2 " , engineConfiguration - > tps1_2AdcChannel , ADC_SLOW ) ;
addChannel ( " TPS2_1 " , engineConfiguration - > tps2_1AdcChannel , ADC_SLOW ) ;
addChannel ( " TPS2_2 " , engineConfiguration - > tps2_2AdcChannel , ADC_SLOW ) ;
2017-03-24 10:41:36 -07:00
addChannel ( " fuel " , engineConfiguration - > fuelLevelSensor , ADC_SLOW ) ;
2019-11-04 14:03:21 -08:00
addChannel ( " pPS " , engineConfiguration - > throttlePedalPositionAdcChannel , ADC_SLOW ) ;
2017-03-24 10:41:36 -07:00
addChannel ( " VBatt " , engineConfiguration - > vbattAdcChannel , ADC_SLOW ) ;
// not currently used addChannel("Vref", engineConfiguration->vRefAdcChannel, ADC_SLOW);
addChannel ( " CLT " , engineConfiguration - > clt . adcChannel , ADC_SLOW ) ;
addChannel ( " IAT " , engineConfiguration - > iat . adcChannel , ADC_SLOW ) ;
2019-12-02 14:49:01 -08:00
addChannel ( " AUXT#1 " , engineConfiguration - > auxTempSensor1 . adcChannel , ADC_SLOW ) ;
addChannel ( " AUXT#2 " , engineConfiguration - > auxTempSensor2 . adcChannel , ADC_SLOW ) ;
2020-03-23 20:15:44 -07:00
if ( engineConfiguration - > auxFastSensor1_adcChannel ! = INCOMPATIBLE_CONFIG_CHANGE ) {
2019-12-02 14:49:01 -08:00
// allow EFI_ADC_0 next time we have an incompatible configuration change
2019-12-11 14:48:55 -08:00
addChannel ( " AUXF#1 " , engineConfiguration - > auxFastSensor1_adcChannel , ADC_FAST ) ;
2019-12-02 14:49:01 -08:00
}
2017-03-24 10:41:36 -07:00
addChannel ( " AFR " , engineConfiguration - > afr . hwChannel , ADC_SLOW ) ;
2017-11-15 11:30:13 -08:00
addChannel ( " OilP " , engineConfiguration - > oilPressure . hwChannel , ADC_SLOW ) ;
2017-03-24 10:41:36 -07:00
addChannel ( " AC " , engineConfiguration - > acSwitchAdc , ADC_SLOW ) ;
2020-03-23 20:15:44 -07:00
if ( engineConfiguration - > high_fuel_pressure_sensor_1 ! = INCOMPATIBLE_CONFIG_CHANGE ) {
2019-05-25 14:18:16 -07:00
addChannel ( " HFP1 " , engineConfiguration - > high_fuel_pressure_sensor_1 , ADC_SLOW ) ;
2020-03-23 20:15:44 -07:00
}
if ( engineConfiguration - > high_fuel_pressure_sensor_2 ! = INCOMPATIBLE_CONFIG_CHANGE ) {
2019-05-25 14:18:16 -07:00
addChannel ( " HFP2 " , engineConfiguration - > high_fuel_pressure_sensor_2 , ADC_SLOW ) ;
2020-03-23 20:15:44 -07:00
}
2017-03-24 10:41:36 -07:00
2019-12-11 14:48:55 -08:00
if ( CONFIG ( isCJ125Enabled ) ) {
2018-01-22 14:45:10 -08:00
addChannel ( " cj125ur " , engineConfiguration - > cj125ur , ADC_SLOW ) ;
addChannel ( " cj125ua " , engineConfiguration - > cj125ua , ADC_SLOW ) ;
}
2017-08-06 16:43:01 -07:00
for ( int i = 0 ; i < FSIO_ANALOG_INPUT_COUNT ; i + + ) {
2017-03-24 10:41:36 -07:00
addChannel ( " FSIOadc " , engineConfiguration - > fsioAdc [ i ] , ADC_SLOW ) ;
}
2019-03-28 19:46:10 -07:00
setAdcChannelOverrides ( ) ;
2017-03-24 10:41:36 -07:00
}
2019-12-11 06:28:11 -08:00
static SlowAdcController slowAdcController ;
2019-08-01 22:36:02 -07:00
void initAdcInputs ( ) {
2017-03-24 10:41:36 -07:00
printMsg ( & logger , " initAdcInputs() " ) ;
if ( ADC_BUF_DEPTH_FAST > MAX_ADC_GRP_BUF_DEPTH )
firmwareError ( CUSTOM_ERR_ADC_DEPTH_FAST , " ADC_BUF_DEPTH_FAST too high " ) ;
if ( ADC_BUF_DEPTH_SLOW > MAX_ADC_GRP_BUF_DEPTH )
firmwareError ( CUSTOM_ERR_ADC_DEPTH_SLOW , " ADC_BUF_DEPTH_SLOW too high " ) ;
configureInputs ( ) ;
// migrate to 'enable adcdebug'
2017-04-04 20:17:56 -07:00
addConsoleActionI ( " adcdebug " , & setAdcDebugReporting ) ;
2017-03-24 10:41:36 -07:00
2019-04-12 17:52:51 -07:00
# if EFI_INTERNAL_ADC
2017-03-24 10:41:36 -07:00
/*
* Initializes the ADC driver .
*/
adcStart ( & ADC_SLOW_DEVICE , NULL ) ;
adcStart ( & ADC_FAST_DEVICE , NULL ) ;
adcSTM32EnableTSVREFE ( ) ; // Internal temperature sensor
for ( int adc = 0 ; adc < HW_MAX_ADC_INDEX ; adc + + ) {
adc_channel_mode_e mode = adcHwChannelEnabled [ adc ] ;
/**
* in board test mode all currently enabled ADC channels are running in slow mode
*/
2019-08-01 22:36:02 -07:00
if ( mode = = ADC_SLOW ) {
2017-03-24 10:41:36 -07:00
slowAdc . enableChannelAndPin ( ( adc_channel_e ) ( ADC_CHANNEL_IN0 + adc ) ) ;
} else if ( mode = = ADC_FAST ) {
fastAdc . enableChannelAndPin ( ( adc_channel_e ) ( ADC_CHANNEL_IN0 + adc ) ) ;
}
}
2019-04-12 17:52:51 -07:00
# if defined(ADC_CHANNEL_SENSOR)
2017-03-24 10:41:36 -07:00
// Internal temperature sensor, Available on ADC1 only
slowAdc . enableChannel ( ( adc_channel_e ) ADC_CHANNEL_SENSOR ) ;
2019-04-01 11:02:19 -07:00
# endif /* ADC_CHANNEL_SENSOR */
2017-03-24 10:41:36 -07:00
slowAdc . init ( ) ;
2019-12-11 06:28:11 -08:00
// Start the slow ADC thread
slowAdcController . Start ( ) ;
2017-04-05 19:41:51 -07:00
2019-12-11 14:48:55 -08:00
if ( CONFIG ( isFastAdcEnabled ) ) {
2017-03-24 10:41:36 -07:00
fastAdc . init ( ) ;
/*
* Initializes the PWM driver .
*/
2019-04-12 17:52:51 -07:00
# if HAL_USE_PWM
2017-03-24 10:41:36 -07:00
pwmStart ( EFI_INTERNAL_FAST_ADC_PWM , & pwmcfg_fast ) ;
2017-04-05 19:41:51 -07:00
pwmEnablePeriodicNotification ( EFI_INTERNAL_FAST_ADC_PWM ) ;
2018-11-16 04:40:06 -08:00
# endif /* HAL_USE_PWM */
2017-03-24 10:41:36 -07:00
}
addConsoleActionI ( " adc " , ( VoidInt ) printAdcValue ) ;
# else
printMsg ( & logger , " ADC disabled " ) ;
# endif
}
void printFullAdcReportIfNeeded ( Logging * logger ) {
if ( ! adcDebugReporting )
return ;
printFullAdcReport ( logger ) ;
}
# endif /* HAL_USE_ADC */