@@ -547,6 +547,22 @@ impl From<DynPclkSourceId> for Genselect {
547547 }
548548}
549549
550+ impl PclkSourceId for DynPclkSourceId {
551+ fn source_id ( & self ) -> DynGclkId {
552+ * self
553+ }
554+ }
555+
556+ impl Sealed for DynPclkSourceId { }
557+
558+ //==============================================================================
559+ // PclkSourceId
560+ //==============================================================================
561+
562+ pub struct PclkSource < G : GclkId > {
563+ _src : PhantomData < G > ,
564+ }
565+
550566//==============================================================================
551567// PclkSourceId
552568//==============================================================================
@@ -566,9 +582,25 @@ impl From<DynPclkSourceId> for Genselect {
566582/// [`Gclk`]: super::gclk::Gclk
567583/// [type-level programming]: crate::typelevel
568584/// [type-level enums]: crate::typelevel#type-level-enums
569- pub trait PclkSourceId : GclkId { }
585+ pub trait PclkSourceId : Sealed {
586+ fn source_id ( & self ) -> DynGclkId ;
587+ }
588+
589+ impl < G : GclkId > PclkSourceId for G {
590+ #[ inline]
591+ fn source_id ( & self ) -> DynGclkId {
592+ Self :: DYN
593+ }
594+ }
570595
571- impl < G : GclkId > PclkSourceId for G { }
596+ impl < G : GclkId > PclkSourceId for PclkSource < G > {
597+ #[ inline]
598+ fn source_id ( & self ) -> DynGclkId {
599+ G :: DYN
600+ }
601+ }
602+
603+ impl < G : GclkId > Sealed for PclkSource < G > { }
572604
573605//==============================================================================
574606// Pclk
@@ -606,24 +638,41 @@ where
606638 I : PclkSourceId ,
607639{
608640 token : PclkToken < P > ,
609- src : PhantomData < I > ,
641+ src : I ,
610642 freq : Hertz ,
611643}
612644
613- impl < P , I > Pclk < P , I >
645+ /// [`Pclk`] with a dynamic source ID ([`DynPclkSourceId`]).
646+ pub type DynPclk < P > = Pclk < P , DynPclkSourceId > ;
647+
648+ impl < P , G > From < Pclk < P , PclkSource < G > > > for DynPclk < P >
614649where
615650 P : PclkId ,
616- I : PclkSourceId ,
651+ G : GclkId ,
652+ {
653+ fn from ( value : Pclk < P , PclkSource < G > > ) -> Self {
654+ Pclk {
655+ token : value. token ,
656+ freq : value. freq ,
657+ src : G :: DYN ,
658+ }
659+ }
660+ }
661+
662+ impl < P , G > Pclk < P , PclkSource < G > >
663+ where
664+ P : PclkId ,
665+ G : GclkId ,
617666{
618667 pub ( super ) fn new ( token : PclkToken < P > , freq : Hertz ) -> Self {
619668 Self {
620669 token,
621- src : PhantomData ,
670+ src : PclkSource { _src : PhantomData } ,
622671 freq,
623672 }
624673 }
625674
626- /// Create and enable a [`Pclk`]
675+ /// Create and enable a [`Pclk`] with a type-checked source ID.
627676 ///
628677 /// Creating a [`Pclk`] immediately enables the corresponding peripheral
629678 /// channel clock. It also [`Increment`]s the [`Source`]'s [`Enabled`]
@@ -636,15 +685,15 @@ where
636685 #[ inline]
637686 pub fn enable < S > ( mut token : PclkToken < P > , gclk : S ) -> ( Self , S :: Inc )
638687 where
639- S : Source < Id = I > + Increment ,
688+ S : Source < Id = G > + Increment ,
640689 {
641690 let freq = gclk. freq ( ) ;
642- token. enable ( I :: DYN ) ;
643- let pclk = Pclk :: new ( token, freq) ;
691+ token. enable ( G :: DYN ) ;
692+ let pclk = Self :: new ( token, freq) ;
644693 ( pclk, gclk. inc ( ) )
645694 }
646695
647- /// Disable and destroy a [`Pclk`]
696+ /// Disable and destroy a [`Pclk`].
648697 ///
649698 /// Consume the [`Pclk`], release the [`PclkToken`], and [`Decrement`] the
650699 /// [`EnabledGclk`]'s counter
@@ -654,12 +703,87 @@ where
654703 #[ inline]
655704 pub fn disable < S > ( mut self , gclk : S ) -> ( PclkToken < P > , S :: Dec )
656705 where
657- S : Source < Id = I > + Decrement ,
706+ S : Source < Id = G > + Decrement ,
707+ {
708+ self . token . disable ( ) ;
709+ ( self . token , gclk. dec ( ) )
710+ }
711+ }
712+
713+ impl < P > DynPclk < P >
714+ where
715+ P : PclkId ,
716+ {
717+ pub ( super ) fn new < G : GclkId > ( token : PclkToken < P > , freq : Hertz ) -> Self {
718+ Self {
719+ token,
720+ src : G :: DYN ,
721+ freq,
722+ }
723+ }
724+
725+ /// Create and enable a [`Pclk`] with an underlying [`DynPclkSourceId`]
726+ /// source ID type.
727+ ///
728+ /// Some peripherals require a dynamic PCLK source ID type parameter; use
729+ /// this method to create a [`Pclk`] where this type parameter is
730+ /// type-erased.
731+ ///
732+ /// Creating a [`Pclk`] immediately enables the corresponding peripheral
733+ /// channel clock. It also [`Increment`]s the [`Source`]'s [`Enabled`]
734+ /// counter.
735+ ///
736+ /// Note that the [`Source`] will always be an [`EnabledGclk`].
737+ ///
738+ /// [`Enabled`]: super::Enabled
739+ /// [`EnabledGclk`]: super::gclk::EnabledGclk
740+ #[ inline]
741+ pub fn enable_dyn < S , G : GclkId > ( mut token : PclkToken < P > , gclk : S ) -> ( Self , S :: Inc )
742+ where
743+ S : Source < Id = G > + Increment ,
658744 {
745+ let freq = gclk. freq ( ) ;
746+ token. enable ( G :: DYN ) ;
747+ let pclk = Self :: new :: < G > ( token, freq) ;
748+ ( pclk, gclk. inc ( ) )
749+ }
750+
751+ /// Disable and destroy a [`Pclk`].
752+ ///
753+ /// Consume the [`Pclk`], release the [`PclkToken`], and [`Decrement`] the
754+ /// [`EnabledGclk`]'s counter.
755+ ///
756+ /// # Panics
757+ ///
758+ /// Panics if the [`Pclk`]'s underlying GCLK source ID does not match the ID
759+ /// of the provided [`Source`].
760+ ///
761+ /// [`Enabled`]: super::Enabled
762+ /// [`EnabledGclk`]: super::gclk::EnabledGclk
763+ #[ inline]
764+ pub fn disable < S , G : GclkId > ( mut self , gclk : S ) -> ( PclkToken < P > , S :: Dec )
765+ where
766+ S : Source < Id = G > + Decrement ,
767+ {
768+ // Make sure that we can only decrement the source we are actually using
769+ assert_eq ! (
770+ G :: DYN ,
771+ self . src,
772+ "Expected GCLK ID {:?}, found {:?}" ,
773+ G :: DYN ,
774+ self . src
775+ ) ;
776+
659777 self . token . disable ( ) ;
660778 ( self . token , gclk. dec ( ) )
661779 }
780+ }
662781
782+ impl < P , I > Pclk < P , I >
783+ where
784+ P : PclkId ,
785+ I : PclkSourceId ,
786+ {
663787 /// Return the [`Pclk`] frequency
664788 #[ inline]
665789 pub fn freq ( & self ) -> Hertz {
0 commit comments