rusefi/firmware/hw_layer/ports/stm32/stm32_adc.cpp

153 lines
4.4 KiB
C++

/**
* @file stm32_common_adc.cpp
* @brief Low level common STM32 code
*
* @date Mar 28, 2019
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "pch.h"
#include "efilib.h"
#if HAL_USE_ADC
static const struct {
brain_pin_e pin;
adc_channel_e ch;
uint8_t adc; /* bitmask of ADC available on this pin */
} adcChannels[] = {
{ Gpio::A0, EFI_ADC_0, BIT(0) | BIT(1) | BIT(2) },
{ Gpio::A1, EFI_ADC_1, BIT(0) | BIT(1) | BIT(2) },
{ Gpio::A2, EFI_ADC_2, BIT(0) | BIT(1) | BIT(2) },
{ Gpio::A3, EFI_ADC_3, BIT(0) | BIT(1) | BIT(2) },
{ Gpio::A4, EFI_ADC_4, BIT(0) | BIT(1) },
{ Gpio::F6, EFI_ADC_32, BIT(2) }, //ADC3 only
{ Gpio::A5, EFI_ADC_5, BIT(0) | BIT(1) },
{ Gpio::F7, EFI_ADC_33, BIT(2) }, //ADC3 only
{ Gpio::A6, EFI_ADC_6, BIT(0) | BIT(1) },
{ Gpio::F8, EFI_ADC_34, BIT(2) }, //ADC3 only
{ Gpio::A7, EFI_ADC_7, BIT(0) | BIT(1) },
{ Gpio::F9, EFI_ADC_35, BIT(2) }, //ADC3 only
{ Gpio::B0, EFI_ADC_8, BIT(0) | BIT(1) },
{ Gpio::F10, EFI_ADC_36, BIT(2) }, //ADC3 only
{ Gpio::B1, EFI_ADC_9, BIT(0) | BIT(1) },
{ Gpio::F3, EFI_ADC_37, BIT(2) }, //ADC3 only
{ Gpio::C0, EFI_ADC_10, BIT(0) | BIT(1) | BIT(2) },
{ Gpio::C1, EFI_ADC_11, BIT(0) | BIT(1) | BIT(2) },
{ Gpio::C2, EFI_ADC_12, BIT(0) | BIT(1) | BIT(2) },
{ Gpio::C3, EFI_ADC_13, BIT(0) | BIT(1) | BIT(2) },
{ Gpio::C4, EFI_ADC_14, BIT(0) | BIT(1) },
{ Gpio::F4, EFI_ADC_38, BIT(2) }, //ADC3 only
{ Gpio::C5, EFI_ADC_15, BIT(0) | BIT(1) },
{ Gpio::F5, EFI_ADC_39, BIT(2) }, //ADC3 only
/* TODO: add ADC3 channels */
};
brain_pin_e getAdcChannelBrainPin(const char *msg, adc_channel_e hwChannel) {
static_assert(EFI_ADC_NONE == ADC_CHANNEL_NONE);
/* Muxed adc inputs */
hwChannel = adcMuxedGetParent(hwChannel);
for (size_t idx = 0; idx < efi::size(adcChannels); idx++) {
if (adcChannels[idx].ch == hwChannel) {
return adcChannels[idx].pin;
}
}
/* todo: what is upper range ADC is used while lower range ADC is not used? how do we still mark pin used?
* external muxes for internal ADC #3350
* firmwareError(ObdCode::CUSTOM_ERR_ADC_UNKNOWN_CHANNEL, "Unknown hw channel %d [%s]", hwChannel, msg);
*/
(void)msg;
return Gpio::Invalid;
}
bool adcIsMuxedInput(adc_channel_e hwChannel) {
#ifdef ADC_MUX_PIN
return ((hwChannel >= EFI_ADC_16) && (hwChannel <= EFI_ADC_31));
#else
return false;
#endif
}
// If mux is not enabled or channel is already a root channel - return itself
adc_channel_e adcMuxedGetParent(adc_channel_e hwChannel)
{
if (adcIsMuxedInput(hwChannel)) {
return (adc_channel_e)(EFI_ADC_0 + (hwChannel - EFI_ADC_16));
}
return hwChannel;
}
adc_channel_e getAdcChannel(brain_pin_e pin) {
if (pin == Gpio::Unassigned)
return EFI_ADC_NONE;
for (size_t idx = 0; idx < efi::size(adcChannels); idx++) {
if (adcChannels[idx].pin == pin) {
return adcChannels[idx].ch;
}
}
criticalError("getAdcChannel %d", pin);
return EFI_ADC_ERROR;
}
// Get ADC internal input index for given hwChannel
int getAdcInternalChannel(ADC_TypeDef *adc, adc_channel_e hwChannel)
{
uint8_t mask = 0;
#if STM32_ADC_USE_ADC1
if (adc == ADC1) {
mask = BIT(0);
}
#endif
#if STM32_ADC_USE_ADC2
if (adc == ADC2) {
mask = BIT(1);
}
#endif
#if STM32_ADC_USE_ADC3
if (adc == ADC3) {
mask = BIT(2);
}
#endif
if (mask == 0) {
// Unknown ADC instance
return -1;
}
int hwIndex = 0;
for (size_t idx = 0; idx < efi::size(adcChannels); idx++) {
if (adcChannels[idx].ch == hwChannel) {
return hwIndex;
}
if (adcChannels[idx].adc & mask) {
hwIndex++;
}
}
// Channel is not supported by this ADC
return -1;
}
// deprecated - inline?
ioportid_t getAdcChannelPort(const char *msg, adc_channel_e hwChannel) {
brain_pin_e brainPin = getAdcChannelBrainPin(msg, hwChannel);
return getHwPort(msg, brainPin);
}
// deprecated - inline?
int getAdcChannelPin(adc_channel_e hwChannel) {
brain_pin_e brainPin = getAdcChannelBrainPin("get_pin", hwChannel);
return getHwPin("get_pin", brainPin);
}
#endif /* HAL_USE_ADC */