Skip to content

Commit 608f8a2

Browse files
committed
[STM32F3/G4/L4/H7] add ext. trigger and offset api
1 parent 7d9070d commit 608f8a2

File tree

2 files changed

+288
-0
lines changed

2 files changed

+288
-0
lines changed

src/modm/platform/adc/stm32f3/adc.hpp.in

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,14 @@ public:
309309
%% endif
310310
};
311311

312+
enum class ExternalTriggerPolarity
313+
{
314+
NoTriggerDetection = 0x0u,
315+
RisingEdge = 0x1u,
316+
FallingEdge = 0x2u,
317+
RisingAndFallingEdge = 0x3u,
318+
};
319+
312320
enum class Interrupt : uint32_t
313321
{
314322
Ready = ADC_IER_ADRDYIE,
@@ -342,6 +350,57 @@ public:
342350
};
343351
MODM_FLAGS32(InterruptFlag);
344352

353+
/**
354+
* Enum mapping all events on a external trigger converter.
355+
* The source mapped to each event varies on controller family,
356+
* refer to the ADC external trigger section on reference manual
357+
* of your controller for more information
358+
*/
359+
enum class RegularConversionExternalTrigger
360+
{
361+
Event0 = 0x00u,
362+
Event1 = 0x01u,
363+
Event2 = 0x02u,
364+
Event3 = 0x03u,
365+
Event4 = 0x04u,
366+
Event5 = 0x05u,
367+
Event6 = 0x06u,
368+
Event7 = 0x07u,
369+
Event9 = 0x09u,
370+
Event10 = 0x0Au,
371+
Event11 = 0x0Bu,
372+
Event12 = 0x0Cu,
373+
Event13 = 0x0Du,
374+
Event14 = 0x0Eu,
375+
Event15 = 0x0Fu,
376+
%% if target["family"] in ["g4"]
377+
Event16 = 0x10u,
378+
Event17 = 0x11u,
379+
Event18 = 0x12u,
380+
Event19 = 0x13u,
381+
Event20 = 0x14u,
382+
Event21 = 0x15u,
383+
Event22 = 0x16u,
384+
Event23 = 0x17u,
385+
Event24 = 0x18u,
386+
Event25 = 0x19u,
387+
Event26 = 0x1Au,
388+
Event27 = 0x1Bu,
389+
Event28 = 0x1Cu,
390+
Event29 = 0x1Du,
391+
Event30 = 0x1Eu,
392+
Event31 = 0x1Fu,
393+
%% endif
394+
};
395+
396+
enum class OffsetSlot : uint8_t
397+
{
398+
Slot0 = 0,
399+
Slot1 = 1,
400+
Slot2 = 2,
401+
Slot3 = 3,
402+
};
403+
345404
public:
346405
template< class... Signals >
347406
static void
@@ -499,6 +558,23 @@ public:
499558
static inline void
500559
stopConversion();
501560

561+
/**
562+
* enable regular conversions on external trigger.
563+
*
564+
* @param externalTriggerPolarity
565+
* Polarity of the external trigger signal.
566+
* @param regularConversionExternalTrigger
567+
* Regular conversion external trigger source.
568+
*/
569+
static inline void enableRegularConversionExternalTrigger(
570+
ExternalTriggerPolarity externalTriggerPolarity,
571+
RegularConversionExternalTrigger regularConversionExternalTrigger);
572+
573+
/**
574+
* Disable regular conversions external trigger.
575+
*/
576+
static inline void disableRegularConversionExternalTrigger( void );
577+
502578
/**
503579
* @return If the conversion is finished.
504580
* @pre A conversion should have been started with startConversion()
@@ -539,6 +615,23 @@ public:
539615
static inline bool
540616
setInjectedConversionSequenceLength(uint8_t length);
541617

618+
/**
619+
* enable injected conversions on external trigger.
620+
*
621+
* @param externalTriggerPolarity
622+
* Polarity of the external trigger signal.
623+
* @param regularConversionExternalTrigger
624+
* Regular conversion external trigger source.
625+
*/
626+
static inline void enableInjectedConversionExternalTrigger(
627+
ExternalTriggerPolarity externalTriggerPolarity,
628+
RegularConversionExternalTrigger regularConversionExternalTrigger);
629+
630+
/**
631+
* Disable injected conversions external trigger.
632+
*/
633+
static inline void disableInjectedConversionExternalTrigger();
634+
542635
/**
543636
* @return If the injected conversion sequence is finished.
544637
* @pre An injected conversion should have been started with startInjectedConversionSequence()
@@ -585,6 +678,76 @@ public:
585678
}
586679
}
587680

681+
%% if target["family"] in ["f3", "l4", "l5"] or (target["family"] in ["h7"] and target["name"][0] in ["4", "5", "a", "b"]):
682+
/**
683+
* @arg slot for the offset register (0..3)
684+
* @arg channel channel to which the offset is applied
685+
* @arg offset offset value to be applied to the channel
686+
* @return true if the offset was successfully enabled, false if the slot is invalid
687+
* @note The offset can only be applied when the adc is stopped!
688+
*/
689+
static inline bool
690+
enableChannelOffset(const OffsetSlot slot, const Channel channel, const uint16_t offset);
691+
692+
/**
693+
* @arg slot for the offset register (0..3)
694+
* @arg offset value applied to the channel
695+
* @return true if the offset was successfully enabled, false if the slot is invalid
696+
* @note The channel is determined by the GPIO pin type.
697+
* @note The offset can only be applied when the adc is stopped!
698+
*/
699+
template<class Gpio>
700+
static inline bool enableChannelOffset(const OffsetSlot slot, const uint16_t offset)
701+
{
702+
return enableChannelOffset(slot, getPinChannel<Gpio>(), offset);
703+
}
704+
705+
%% else
706+
/**
707+
* @arg slot for the offset register (0..3)
708+
* @arg channel channel to which the offset is applied
709+
* @arg offset offset value to be applied to the channel
710+
* @arg saturate if true, the adc result value is saturated to the range of the ADC
711+
* @return true if the offset was successfully enabled, false if the slot is invalid
712+
* @note The offset can only be applied when the adc is stopped!
713+
*/
714+
static inline bool
715+
enableChannelOffset(const OffsetSlot slot, const Channel channel, const int16_t offset, const bool saturate = false);
716+
717+
/**
718+
* @arg slot for the offset register (0..3)
719+
* @arg offset value applied to the channel
720+
* @arg saturate if true, the adc result value is saturated to the range of the ADC
721+
* @return true if the offset was successfully enabled, false if the slot is invalid
722+
* @note The channel is determined by the GPIO pin type.
723+
* @note The offset can only be applied when the adc is stopped!
724+
*/
725+
template<class Gpio>
726+
static inline bool enableChannelOffset(const OffsetSlot slot, const int16_t offset, const bool saturate = false)
727+
{
728+
return enableChannelOffset(slot, getPinChannel<Gpio>(), offset, saturate);
729+
}
730+
%% endif
731+
732+
/**
733+
* @arg slot for the offset register (0..3)
734+
* @return true if the offset was successfully disabled, false if the slot is invalid
735+
* @note The offset can only be disabled when the adc is stopped!
736+
*/
737+
static inline bool disableChannelOffset(OffsetSlot slot);
738+
739+
/**
740+
* @arg slot for the offset register (0..3)
741+
* @return true if the offset was successfully disabled, false if the slot is invalid
742+
* @note The channel is determined by the GPIO pin type.
743+
* @note The offset can only be disabled when the adc is stopped!
744+
*/
745+
template<class Gpio>
746+
static inline bool disableChannelOffset(OffsetSlot slot)
747+
{
748+
return disableChannelOffset(slot);
749+
}
750+
588751
static inline void
589752
enableInterruptVector(const uint32_t priority, const bool enable = true);
590753

src/modm/platform/adc/stm32f3/adc_impl.hpp.in

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,25 @@ modm::platform::Adc{{ id }}::isConversionSequenceFinished()
302302
return static_cast<bool>(getInterruptFlags() & InterruptFlag::EndOfRegularSequenceOfConversions);
303303
}
304304

305+
void
306+
modm::platform::Adc{{ id }}::enableRegularConversionExternalTrigger(
307+
ExternalTriggerPolarity externalTriggerPolarity,
308+
RegularConversionExternalTrigger regularConversionExternalTrigger)
309+
{
310+
const auto polarity = (static_cast<uint32_t>(externalTriggerPolarity) << ADC_CFGR_EXTEN_Pos);
311+
const auto externalTrigger = (static_cast<uint32_t>(regularConversionExternalTrigger) << ADC_CFGR_EXTSEL_Pos);
312+
const auto mask = ADC_CFGR_EXTEN_Msk | ADC_CFGR_EXTSEL_Msk;
313+
ADC{{ id }}->CFGR = (ADC{{ id }}->CFGR & ~mask) | polarity | externalTrigger;
314+
}
315+
316+
void
317+
modm::platform::Adc{{ id }}::disableRegularConversionExternalTrigger()
318+
{
319+
// Disable regular conversions external trigger by clearing the bits
320+
// for polarity and external trigger source.
321+
ADC{{ id }}->CFGR &= ~(ADC_CFGR_EXTEN_Msk | ADC_CFGR_EXTSEL_Msk);
322+
}
323+
305324
void
306325
modm::platform::Adc{{ id }}::startInjectedConversionSequence()
307326
{
@@ -351,6 +370,26 @@ modm::platform::Adc{{ id }}::setInjectedConversionSequenceLength(uint8_t length)
351370
return true;
352371
}
353372

373+
void
374+
modm::platform::Adc{{ id }}::enableInjectedConversionExternalTrigger(
375+
ExternalTriggerPolarity externalTriggerPolarity,
376+
RegularConversionExternalTrigger regularConversionExternalTrigger)
377+
{
378+
const auto polarity = (static_cast<uint32_t>(externalTriggerPolarity) << ADC_JSQR_JEXTEN_Pos);
379+
const auto externalTrigger =
380+
(static_cast<uint32_t>(regularConversionExternalTrigger) << ADC_JSQR_JEXTSEL_Pos);
381+
const auto mask = ADC_JSQR_JEXTEN_Msk | ADC_JSQR_JEXTSEL_Msk;
382+
ADC{{ id }}->JSQR = (ADC{{ id }}->JSQR & ~mask) | polarity | externalTrigger;
383+
}
384+
385+
void
386+
modm::platform::Adc{{ id }}::disableInjectedConversionExternalTrigger()
387+
{
388+
// Disable injected conversions external trigger by clearing the bits
389+
// for polarity and external trigger source.
390+
ADC{{id}}->JSQR &= ~(ADC_JSQR_JEXTEN_Msk | ADC_JSQR_JEXTSEL_Msk);
391+
}
392+
354393
bool
355394
modm::platform::Adc{{ id }}::isInjectedConversionFinished()
356395
{
@@ -410,3 +449,89 @@ modm::platform::Adc{{ id }}::acknowledgeInterruptFlags(const InterruptFlag_t fla
410449
// Writing a zero is ignored.
411450
ADC{{ id }}->ISR = flags.value;
412451
}
452+
453+
%% if target["family"] in ["f3", "l4", "l5"] or (target["family"] in ["h7"] and target["name"][0] in ["4", "5", "a", "b"]):
454+
bool
455+
modm::platform::Adc{{ id }}::enableChannelOffset( const OffsetSlot slot, const Channel channel, const uint16_t offset)
456+
{
457+
const uint32_t offsetMask = (offset << ADC_OFR1_OFFSET1_Pos) & ADC_OFR1_OFFSET1_Msk;
458+
const uint32_t signMask = 0u;
459+
const uint32_t saturateMask = 0u;
460+
%% else
461+
bool
462+
modm::platform::Adc{{ id }}::enableChannelOffset( const OffsetSlot slot, const Channel channel, const int16_t offset, const bool saturate)
463+
{
464+
const uint32_t offsetMask = (std::abs(offset) << ADC_OFR1_OFFSET1_Pos) & ADC_OFR1_OFFSET1_Msk;
465+
%% if target["family"] in["h7"]
466+
%# H7 names the bits differently, but the logic is the same
467+
const uint32_t signMask = (offset > 0) ? ADC3_OFR1_OFFSETPOS : 0u;
468+
const uint32_t saturateMask = saturate ? ADC3_OFR1_SATEN : 0u;
469+
%% else
470+
const uint32_t signMask = (offset > 0) ? ADC_OFR1_OFFSETPOS : 0u;
471+
const uint32_t saturateMask = saturate ? ADC_OFR1_SATEN : 0u;
472+
%% endif
473+
%% endif
474+
%% if target["family"] in ["h7"]
475+
%% if target["name"][0] in ["4" , "5", "a", "b"]
476+
%# no specific enable bit for H74x/H75x, so always 0
477+
const uint32_t enableMask = 0u;
478+
%% else
479+
%# H7 uses a different register bit names
480+
const uint32_t enableMask = ADC3_OFR1_OFFSET1_EN;
481+
%% endif
482+
%% else
483+
const uint32_t enableMask = ADC_OFR1_OFFSET1_EN;
484+
%% endif
485+
const uint32_t channelMask = (static_cast<uint32_t>(channel) << ADC_OFR1_OFFSET1_CH_Pos) & ADC_OFR1_OFFSET1_CH_Msk;
486+
const uint32_t offsetValue = channelMask | offsetMask | enableMask | saturateMask | signMask;
487+
488+
if ((ADC{{id}}->CR & ADC_CR_JADSTART) || (ADC{{id}}->CR & ADC_CR_ADSTART))
489+
{
490+
// ADC is currently converting, cannot set offset
491+
return false;
492+
}
493+
494+
switch (slot)
495+
{
496+
case OffsetSlot::Slot0: ADC{{id}}->OFR1 = offsetValue; break;
497+
case OffsetSlot::Slot1: ADC{{id}}->OFR2 = offsetValue; break;
498+
case OffsetSlot::Slot2: ADC{{id}}->OFR3 = offsetValue; break;
499+
case OffsetSlot::Slot3: ADC{{id}}->OFR4 = offsetValue; break;
500+
default:
501+
return false; // invalid slot
502+
}
503+
504+
return true;
505+
}
506+
507+
bool
508+
modm::platform::Adc{{ id }}::disableChannelOffset(const OffsetSlot slot)
509+
{
510+
if ( (ADC{{ id }}->CR & ADC_CR_JADSTART) || (ADC{{ id }}->CR & ADC_CR_ADSTART) ) {
511+
// ADC is currently converting, cannot disable offset
512+
return false;
513+
}
514+
515+
%% if target["family"] in ["h7"]
516+
%% if target["name"][0] in ["4" , "5", "a", "b"]
517+
%# no specific enable bit for H74x/H75x, so always 0
518+
const uint32_t enableMask = ADC_OFR1_OFFSET1_Msk;
519+
%% else
520+
%#H7 uses a different register bit names
521+
const uint32_t enableMask = ADC3_OFR1_OFFSET1_EN;
522+
%% endif
523+
%% else
524+
const uint32_t enableMask = ADC_OFR1_OFFSET1_EN;
525+
%%endif
526+
527+
switch (slot)
528+
{
529+
case OffsetSlot::Slot0: ADC{{id}}->OFR1 &= ~enableMask; break;
530+
case OffsetSlot::Slot1: ADC{{id}}->OFR2 &= ~enableMask; break;
531+
case OffsetSlot::Slot2: ADC{{id}}->OFR3 &= ~enableMask; break;
532+
case OffsetSlot::Slot3: ADC{{id}}->OFR4 &= ~enableMask; break;
533+
default:
534+
return false; // invalid slot
535+
}
536+
return true;
537+
}

0 commit comments

Comments
 (0)