Skip to content

Feature: STM32 ADC trigger and offsets api #1275

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions src/modm/platform/adc/stm32f3/adc.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,14 @@ public:
%% endif
};

enum class ExternalTriggerPolarity
{
NoTriggerDetection = 0x0u,
RisingEdge = 0x1u,
FallingEdge = 0x2u,
RisingAndFallingEdge = 0x3u,
};

enum class Interrupt : uint32_t
{
Ready = ADC_IER_ADRDYIE,
Expand Down Expand Up @@ -342,6 +350,57 @@ public:
};
MODM_FLAGS32(InterruptFlag);

/**
* Enum mapping all events on a external trigger converter.
* The source mapped to each event varies on controller family,
* refer to the ADC external trigger section on reference manual
* of your controller for more information
*/
enum class RegularConversionExternalTrigger
{
Event0 = 0x00u,
Event1 = 0x01u,
Event2 = 0x02u,
Event3 = 0x03u,
Event4 = 0x04u,
Event5 = 0x05u,
Event6 = 0x06u,
Event7 = 0x07u,
Event9 = 0x09u,
Event10 = 0x0Au,
Event11 = 0x0Bu,
Event12 = 0x0Cu,
Event13 = 0x0Du,
Event14 = 0x0Eu,
Event15 = 0x0Fu,
%% if target["family"] in ["g4"]
Event16 = 0x10u,
Event17 = 0x11u,
Event18 = 0x12u,
Event19 = 0x13u,
Event20 = 0x14u,
Event21 = 0x15u,
Event22 = 0x16u,
Event23 = 0x17u,
Event24 = 0x18u,
Event25 = 0x19u,
Event26 = 0x1Au,
Event27 = 0x1Bu,
Event28 = 0x1Cu,
Event29 = 0x1Du,
Event30 = 0x1Eu,
Event31 = 0x1Fu,
%% endif
};

enum class OffsetSlot : uint8_t
{
Slot0 = 0,
Slot1 = 1,
Slot2 = 2,
Slot3 = 3,
};

public:
template< class... Signals >
static void
Expand Down Expand Up @@ -499,6 +558,18 @@ public:
static inline void
stopConversion();

/**
* enable regular conversions on external trigger.
*
* @param externalTriggerPolarity
* Polarity of the external trigger signal.
* @param regularConversionExternalTrigger
* Regular conversion external trigger source.
*/
static inline void enableRegularConversionExternalTrigger(
ExternalTriggerPolarity externalTriggerPolarity,
RegularConversionExternalTrigger regularConversionExternalTrigger);

/**
* @return If the conversion is finished.
* @pre A conversion should have been started with startConversion()
Expand Down Expand Up @@ -539,6 +610,18 @@ public:
static inline bool
setInjectedConversionSequenceLength(uint8_t length);

/**
* enable injected conversions on external trigger.
*
* @param externalTriggerPolarity
* Polarity of the external trigger signal.
* @param regularConversionExternalTrigger
* Regular conversion external trigger source.
*/
static inline void enableInjectedConversionExternalTrigger(
ExternalTriggerPolarity externalTriggerPolarity,
RegularConversionExternalTrigger regularConversionExternalTrigger);

/**
* @return If the injected conversion sequence is finished.
* @pre An injected conversion should have been started with startInjectedConversionSequence()
Expand Down Expand Up @@ -585,6 +668,25 @@ public:
}
}

/**
* @arg slot for the offset register (0..3)
* @arg channel channel to which the offset is applied
* @arg offset offset value to be applied to the channel
*/
static inline bool
setChannelOffset(OffsetSlot slot, Channel channel, int16_t offset, bool saturate = false, bool enable = true);

/**
* @arg slot for the offset register (0..3)
* @return offset value applied to the channel
*/
template<class Gpio>
static inline bool
setChannelOffset(OffsetSlot slot, int16_t offset, bool saturate = false, bool enable = true)
{
return setChannelOffset(slot, getPinChannel<Gpio>(), offset, saturate, enable);
}

static inline void
enableInterruptVector(const uint32_t priority, const bool enable = true);

Expand Down
59 changes: 59 additions & 0 deletions src/modm/platform/adc/stm32f3/adc_impl.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,17 @@ modm::platform::Adc{{ id }}::isConversionSequenceFinished()
return static_cast<bool>(getInterruptFlags() & InterruptFlag::EndOfRegularSequenceOfConversions);
}

void
modm::platform::Adc{{ id }}::enableRegularConversionExternalTrigger(
ExternalTriggerPolarity externalTriggerPolarity,
RegularConversionExternalTrigger regularConversionExternalTrigger)
{
const auto polarity = (static_cast<uint32_t>(externalTriggerPolarity) << ADC_CFGR_EXTEN_Pos);
const auto externalTrigger = (static_cast<uint32_t>(regularConversionExternalTrigger) << ADC_CFGR_EXTSEL_Pos);
const auto mask = ADC_CFGR_EXTEN_Msk | ADC_CFGR_EXTSEL_Msk;
ADC{{ id }}->CFGR = (ADC{{ id }}->CFGR & ~mask) | polarity | externalTrigger;
}

void
modm::platform::Adc{{ id }}::startInjectedConversionSequence()
{
Expand Down Expand Up @@ -351,6 +362,19 @@ modm::platform::Adc{{ id }}::setInjectedConversionSequenceLength(uint8_t length)
return true;
}

void
modm::platform::Adc{{ id }}::enableInjectedConversionExternalTrigger(
ExternalTriggerPolarity externalTriggerPolarity,
RegularConversionExternalTrigger regularConversionExternalTrigger)
{
const auto polarity = (static_cast<uint32_t>(externalTriggerPolarity) << ADC_JSQR_JEXTEN_Pos);
const auto externalTrigger =
(static_cast<uint32_t>(regularConversionExternalTrigger) << ADC_JSQR_JEXTSEL_Pos);
const auto mask = ADC_JSQR_JEXTEN_Msk | ADC_JSQR_JEXTSEL_Msk;
ADC{{ id }}->JSQR = (ADC{{ id }}->JSQR & ~mask) | polarity | externalTrigger;
}


bool
modm::platform::Adc{{ id }}::isInjectedConversionFinished()
{
Expand Down Expand Up @@ -410,3 +434,38 @@ modm::platform::Adc{{ id }}::acknowledgeInterruptFlags(const InterruptFlag_t fla
// Writing a zero is ignored.
ADC{{ id }}->ISR = flags.value;
}

/**
* @arg slot for the offset register (0..3)
* @arg channel channel to which the offset is applied
* @arg offset offset value to be applied to the channel
* @return true if configuration is successful, false if the ADC is currently converting
*/
bool
modm::platform::Adc{{ id }}::setChannelOffset(OffsetSlot slot, Channel channel, int16_t offset,
bool saturate, bool enable)
{
if ( (ADC{{ id }}->CR & ADC_CR_JADSTART) || (ADC{{ id }}->CR & ADC_CR_ADSTART) ) {
// ADC is currently converting, cannot set offset
return false;
}

const uint32_t channelMask = (static_cast<uint32_t>(channel) << ADC_OFR1_OFFSET1_CH_Pos) & ADC_OFR1_OFFSET1_CH_Msk;
const uint32_t offsetMask = (std::abs(offset) << ADC_OFR1_OFFSET1_Pos) & ADC_OFR1_OFFSET1_Msk;
const uint32_t saturateMask = saturate ? ADC_OFR1_SATEN : 0u;
const uint32_t enableMask = enable ? ADC_OFR1_OFFSET1_EN : 0u;
const uint32_t signMask = (offset > 0) ? ADC_OFR1_OFFSETPOS : 0u;
const uint32_t offsetValue = channelMask | offsetMask | saturateMask | enableMask | signMask;

switch (slot)
{
case OffsetSlot::Slot0: ADC{{id}}->OFR1 = offsetValue; break;
case OffsetSlot::Slot1: ADC{{id}}->OFR2 = offsetValue; break;
case OffsetSlot::Slot2: ADC{{id}}->OFR3 = offsetValue; break;
case OffsetSlot::Slot3: ADC{{id}}->OFR4 = offsetValue; break;
default:
return false; // invalid slot
}

return true;
}
Loading