2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file adc_inputs.h
|
2017-11-24 14:40:20 -08:00
|
|
|
* @brief Low level internal ADC code
|
2015-07-10 06:01:56 -07:00
|
|
|
*
|
|
|
|
* @date Jan 14, 2013
|
2020-01-07 21:02:40 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
2020-02-18 05:16:19 -08:00
|
|
|
#pragma once
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2018-09-16 19:26:57 -07:00
|
|
|
#include "global.h"
|
2019-01-31 08:57:15 -08:00
|
|
|
#include "adc_math.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-07-23 11:50:35 -07:00
|
|
|
#ifndef SLOW_ADC_RATE
|
2020-08-21 16:47:12 -07:00
|
|
|
#define SLOW_ADC_RATE 500
|
2021-07-23 11:50:35 -07:00
|
|
|
#endif
|
2020-08-21 16:47:12 -07:00
|
|
|
|
2023-01-08 14:29:29 -08:00
|
|
|
float getAnalogInputDividerCoefficient(adc_channel_e);
|
|
|
|
|
2024-03-28 18:20:40 -07:00
|
|
|
inline bool isAdcChannelValid(adc_channel_e hwChannel) {
|
2024-05-05 05:34:46 -07:00
|
|
|
/* Compiler will optimize, keep following if as a reminder */
|
|
|
|
if (hwChannel >= EFI_ADC_TOTAL_CHANNELS) {
|
2021-01-05 13:02:20 -08:00
|
|
|
/* this should not happen!
|
|
|
|
* if we have enum out of range somewhere in settings
|
|
|
|
* that means something goes terribly wrong
|
|
|
|
* TODO: should we say something?
|
|
|
|
*/
|
|
|
|
return false;
|
|
|
|
}
|
2024-05-05 05:34:46 -07:00
|
|
|
return ((hwChannel > EFI_ADC_NONE) && (hwChannel < EFI_ADC_TOTAL_CHANNELS));
|
2021-01-05 13:02:20 -08:00
|
|
|
}
|
|
|
|
|
2024-05-05 05:55:03 -07:00
|
|
|
inline bool isAdcChannelOnChip(adc_channel_e hwChannel) {
|
|
|
|
return (isAdcChannelValid(hwChannel) && (hwChannel <= EFI_ADC_ONCHIP_LAST));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool isAdcChannelOffChip(adc_channel_e hwChannel) {
|
|
|
|
return (isAdcChannelValid(hwChannel) && (hwChannel > EFI_ADC_ONCHIP_LAST));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-05-31 20:36:30 -07:00
|
|
|
#if !defined(GPT_FREQ_FAST) || !defined(GPT_PERIOD_FAST)
|
2024-06-25 13:31:04 -07:00
|
|
|
|
|
|
|
/*
|
2023-05-31 20:36:30 -07:00
|
|
|
* 8000 RPM is 133Hz
|
2024-06-25 13:31:04 -07:00
|
|
|
* If we want to sample MAP once per 5 degrees we need 133Hz * (360 / 5) = 9576Hz of fast ADC ~= 10 KHz
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO: migrate to continuous ADC mode? probably not - we cannot afford the callback in continuous mode.
|
|
|
|
* TODO: look into other options
|
|
|
|
* TODO: ADC convertion can be triggered directly from timer, with no SW intervention
|
2023-05-31 20:36:30 -07:00
|
|
|
*/
|
2024-06-25 13:31:04 -07:00
|
|
|
|
|
|
|
/* PWM clock frequency. Timer clock = 100 KHz */
|
|
|
|
#define GPT_FREQ_FAST 100000
|
|
|
|
/* PWM period (in PWM ticks), 100 KHz / 10 = 10KHz callback rate */
|
|
|
|
#define GPT_PERIOD_FAST 10
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have 1 / (GPT_FREQ_FAST / GPT_PERIOD_FAST) to finish conversion = 100 uS
|
|
|
|
* With ADC_SAMPLING_FAST = 28 ADC clock @ 21 MHz (F4) -> one channel conversion takes 1.33(3) uS
|
|
|
|
* Oversampling is ADC_BUF_DEPTH_FAST = 4
|
|
|
|
* We can do up-to 100 / (1.33(3) * 4) = 18.75 channels conversions
|
|
|
|
* So we can enable ALL channels for fast ADC.
|
|
|
|
* This will increase bus load with more DMA transfers, but who cares?
|
|
|
|
*/
|
|
|
|
|
2023-05-31 20:36:30 -07:00
|
|
|
#endif /* GPT_FREQ_FAST GPT_PERIOD_FAST */
|
|
|
|
|
2020-08-21 19:07:55 -07:00
|
|
|
#if HAL_USE_ADC
|
|
|
|
|
2024-07-22 16:47:57 -07:00
|
|
|
enum class AdcChannelMode : char {
|
|
|
|
Off,
|
|
|
|
Slow,
|
|
|
|
Fast
|
|
|
|
};
|
2022-09-10 23:16:47 -07:00
|
|
|
|
2024-07-22 16:47:57 -07:00
|
|
|
AdcChannelMode getAdcMode(adc_channel_e hwChannel);
|
2019-08-01 22:36:02 -07:00
|
|
|
void initAdcInputs();
|
2017-04-21 17:07:17 -07:00
|
|
|
|
2017-08-07 04:28:21 -07:00
|
|
|
// wait until at least 1 slowADC sampling is complete
|
2024-07-20 19:09:15 -07:00
|
|
|
void waitForSlowAdc(uint32_t lastAdcCounter = 1);
|
2017-08-07 04:28:21 -07:00
|
|
|
|
2021-05-03 13:44:19 -07:00
|
|
|
void printFullAdcReportIfNeeded(void);
|
2015-07-10 06:01:56 -07:00
|
|
|
int getInternalAdcValue(const char *msg, adc_channel_e index);
|
2016-07-19 19:03:16 -07:00
|
|
|
float getMCUInternalTemperature(void);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2024-07-22 16:28:17 -07:00
|
|
|
void addFastAdcChannel(const char *name, adc_channel_e hwChannel);
|
2024-05-05 08:51:47 -07:00
|
|
|
void removeChannel(const char *name, adc_channel_e hwChannel);
|
2019-03-28 19:46:10 -07:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#define getAdcValue(msg, hwChannel) getInternalAdcValue(msg, hwChannel)
|
|
|
|
|
2023-01-08 14:29:29 -08:00
|
|
|
#define adcToVoltsDivided(adc, hwChannel) (adcToVolts(adc) * getAnalogInputDividerCoefficient(hwChannel))
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-07-23 11:19:59 -07:00
|
|
|
// This callback is called by the ADC driver when a new fast ADC sample is ready
|
|
|
|
void onFastAdcComplete(adcsample_t* samples);
|
2021-10-07 05:29:01 -07:00
|
|
|
|
2024-06-20 03:00:27 -07:00
|
|
|
using AdcToken = uint32_t;
|
|
|
|
|
|
|
|
using AdcTockenInternal = union {
|
|
|
|
AdcToken token;
|
|
|
|
struct {
|
|
|
|
uint16_t adc;
|
|
|
|
uint16_t channel;
|
|
|
|
} __attribute__((packed));
|
|
|
|
};
|
|
|
|
|
|
|
|
static_assert(sizeof(AdcTockenInternal) == sizeof(AdcToken));
|
|
|
|
|
2024-05-12 09:08:01 -07:00
|
|
|
static constexpr AdcToken invalidAdcToken = (AdcToken)(-1);
|
2021-10-07 05:29:01 -07:00
|
|
|
|
2024-05-12 09:08:01 -07:00
|
|
|
AdcToken enableFastAdcChannel(const char* msg, adc_channel_e channel);
|
|
|
|
adcsample_t getFastAdc(AdcToken token);
|
2021-10-07 05:29:01 -07:00
|
|
|
#endif // HAL_USE_ADC
|
|
|
|
|
|
|
|
void printFullAdcReport(void);
|