//! Implementations of the [`IsPad`], [`IsI2cPad`], [`GetPad`] traits

use crate::gpio::v2::*;
use crate::sercom::v2::*;

//==============================================================================
//  Pad definitions
//==============================================================================

macro_rules! pad_info {
    // This is the entry pattern when the pad is not I2C enabled.
    (
        $PinId:ident,
        $Cfg:ident,
        $Sercom:ident,
        $PadNum:ident
    ) => {
        pad_info!(@impl_pad, $PinId, $Cfg, $Sercom, $PadNum);
    };

    // This is the entry pattern when the pad is I2C enabled.
    (
        $PinId:ident,
        $Cfg:ident,
        $Sercom:ident,
        $PadNum:ident
        + I2C
    ) => {
        impl IsI2cPad for Pin<$PinId, Alternate<$Cfg>> {}
        pad_info!(@impl_pad, $PinId, $Cfg, $Sercom, $PadNum);
    };

    (
        @impl_pad,
        $PinId:ident,
        $Cfg:ident,
        $Sercom:ident,
        $PadNum:ident
    ) => {
        #[cfg(feature = "samc11")]
        impl GetPad<$Sercom, $PadNum> for $PinId {
            type PinMode = Alternate<$Cfg>;
        }

        #[cfg(feature = "samc21")]
        impl GetPad<$Sercom> for $PinId {
            type PadNum = $PadNum;
            type PinMode = Alternate<$Cfg>;
        }

        impl IsPad for Pin<$PinId, Alternate<$Cfg>> {
            type Sercom = $Sercom;
            type PadNum = $PadNum;
        }
    };
}

// Feature gates can be placed on individual configurations or on the entire pin
macro_rules! pad_table {
    (
        #[$cfg:meta]
        $PinId:ident {
            $(
                $Cfg:ident: ( $Sercom:ident, $PadNum:ident ) $( + $I2C:ident )?,
            )+
        }
    ) => {
        $(
            #[$cfg]
            pad_info!( $PinId, $Cfg, $Sercom, $PadNum $( + $I2C )? );
        )+
    };

    (
        $PinId:ident {
            $(
                $( #[$cfg:meta] )?
                $Cfg:ident: ( $Sercom:ident, $PadNum:ident ) $( + $I2C:ident )?,
            )+
        }
    ) => {
        $(
            $( #[$cfg] )?
            pad_info!( $PinId, $Cfg, $Sercom, $PadNum $( + $I2C )?  );
        )+
    };

    (
        $(
            $( #[$id_cfg:meta] )?
            $PinId:ident {
                $(
                    $( #[$sercom_cfg:meta] )?
                    $Cfg:ident: ( $Sercom:ident, $PadNum:ident ) $( + $I2C:ident )?,
                )+
            }
        )+
    ) => {
        $(
            pad_table!(
                $( #[$id_cfg] )?
                $PinId {
                    $(
                        $( #[$sercom_cfg] )?
                        $Cfg: ( $Sercom, $PadNum ) $( + $I2C )?,
                    )+
                }
            );
        )+
    };
}

pad_table!(
    #[cfg(feature = "samc21")]
    PA00 {
        D: (Sercom1, Pad0),
    }
    #[cfg(feature = "samc21")]
    PA01 {
        D: (Sercom1, Pad1),
    }
   #[cfg(feature = "samc21")]
    PA06 {
        D: (Sercom0, Pad2),
    }
    #[cfg(feature = "samc21")]
    PA07 {
        D: (Sercom0, Pad3),
    }
    PA08 {
         #[cfg(feature = "samc21")]
        C: (Sercom0, Pad0) + I2C,
        #[cfg(feature = "samc21")]
        D: (Sercom2, Pad0) + I2C,
    }
    PA09 {
        #[cfg(feature = "samc21")]
        C: (Sercom0, Pad1) + I2C,
        #[cfg(feature = "samc21")]
        D: (Sercom2, Pad1) + I2C,
    }
    #[cfg(feature = "samc21")]
    PA10 {
        C: (Sercom0, Pad2),
        D: (Sercom2, Pad2),
    }
    #[cfg(feature = "samc21")]
    PA11 {
        C: (Sercom0, Pad3),
        D: (Sercom2, Pad3),
    }
   PA14 {
        #[cfg(feature = "samc21")]
        C: (Sercom2, Pad2),
    }
    PA15 {
       #[cfg(feature = "samc21")]
        C: (Sercom2, Pad3),
   }
    #[cfg(feature = "samc21")]
    PA16 {
        C: (Sercom1, Pad0) + I2C,
        D: (Sercom3, Pad0) + I2C,
    }
    #[cfg(feature = "samc21")]
    PA17 {
        C: (Sercom1, Pad1) + I2C,
        D: (Sercom3, Pad1) + I2C,
    }
    #[cfg(feature = "samc21")]
    PA18 {
        C: (Sercom1, Pad2),
        D: (Sercom3, Pad2),
    }
    #[cfg(feature = "samc21")]
    PA19 {
        C: (Sercom1, Pad3),
        D: (Sercom3, Pad3),
    }
   PA22 {
        #[cfg(feature = "samc21")]
        C: (Sercom3, Pad0) + I2C,
    }
    PA23 {
        #[cfg(feature = "samc21")]
        C: (Sercom3, Pad1) + I2C,
   }
    PA24 {
        #[cfg(feature = "samc21")]
        C: (Sercom3, Pad2),
   }
    PA25 {
        #[cfg(feature = "samc21")]
        C: (Sercom3, Pad3),
    }
);
