Check group configuration validity

This commit is contained in:
Karun 2024-05-03 17:29:21 -04:00
parent 8e92e8718d
commit a91f686544

View file

@ -215,10 +215,15 @@ impl Default for Config {
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct TscPin<'d, T, C> { pub struct TscPin<'d, T, C> {
_pin: PeripheralRef<'d, AnyPin>, _pin: PeripheralRef<'d, AnyPin>,
_role: PinType, role: PinType,
phantom: PhantomData<(T, C)>, phantom: PhantomData<(T, C)>,
} }
enum GroupError {
NoSample,
ChannelShield,
}
/// Pin group definition /// Pin group definition
/// Pins are organized into groups of four IOs, all groups with a /// Pins are organized into groups of four IOs, all groups with a
/// sampling channel must also have a sampling capacitor channel. /// sampling channel must also have a sampling capacitor channel.
@ -241,6 +246,119 @@ impl<'d, T: Instance, C> PinGroup<'d, T, C> {
d4: None, d4: None,
} }
} }
fn contains_shield(&self) -> bool {
let mut shield_count = 0;
if let Some(pin) = &self.d1 {
if let PinType::Shield = pin.role {
shield_count += 1;
}
}
if let Some(pin) = &self.d2 {
if let PinType::Shield = pin.role {
shield_count += 1;
}
}
if let Some(pin) = &self.d3 {
if let PinType::Shield = pin.role {
shield_count += 1;
}
}
if let Some(pin) = &self.d4 {
if let PinType::Shield = pin.role {
shield_count += 1;
}
}
shield_count == 1
}
fn check_group(&self) -> Result<(), GroupError> {
let mut channel_count = 0;
let mut shield_count = 0;
let mut sample_count = 0;
if let Some(pin) = &self.d1 {
match pin.role {
PinType::Channel => {
channel_count += 1;
}
PinType::Shield => {
shield_count += 1;
}
PinType::Sample => {
sample_count += 1;
}
}
}
if let Some(pin) = &self.d2 {
match pin.role {
PinType::Channel => {
channel_count += 1;
}
PinType::Shield => {
shield_count += 1;
}
PinType::Sample => {
sample_count += 1;
}
}
}
if let Some(pin) = &self.d3 {
match pin.role {
PinType::Channel => {
channel_count += 1;
}
PinType::Shield => {
shield_count += 1;
}
PinType::Sample => {
sample_count += 1;
}
}
}
if let Some(pin) = &self.d4 {
match pin.role {
PinType::Channel => {
channel_count += 1;
}
PinType::Shield => {
shield_count += 1;
}
PinType::Sample => {
sample_count += 1;
}
}
}
// Every group requires one sampling capacitor
if sample_count != 1 {
return Err(GroupError::NoSample);
}
// Each group must have at least one shield or channel IO
if shield_count == 0 && channel_count == 0 {
return Err(GroupError::ChannelShield);
}
// Any group can either contain channel ios or a shield IO
if shield_count != 0 && channel_count != 0 {
return Err(GroupError::ChannelShield);
}
// No more than one shield IO is allow per group and amongst all groups
if shield_count > 1 {
return Err(GroupError::ChannelShield);
}
Ok(())
}
} }
macro_rules! group_impl { macro_rules! group_impl {
@ -261,7 +379,7 @@ macro_rules! group_impl {
); );
self.d1 = Some(TscPin { self.d1 = Some(TscPin {
_pin: pin.map_into(), _pin: pin.map_into(),
_role: role, role: role,
phantom: PhantomData, phantom: PhantomData,
}) })
}) })
@ -282,7 +400,7 @@ macro_rules! group_impl {
); );
self.d2 = Some(TscPin { self.d2 = Some(TscPin {
_pin: pin.map_into(), _pin: pin.map_into(),
_role: role, role: role,
phantom: PhantomData, phantom: PhantomData,
}) })
}) })
@ -303,7 +421,7 @@ macro_rules! group_impl {
); );
self.d3 = Some(TscPin { self.d3 = Some(TscPin {
_pin: pin.map_into(), _pin: pin.map_into(),
_role: role, role: role,
phantom: PhantomData, phantom: PhantomData,
}) })
}) })
@ -324,7 +442,7 @@ macro_rules! group_impl {
); );
self.d4 = Some(TscPin { self.d4 = Some(TscPin {
_pin: pin.map_into(), _pin: pin.map_into(),
_role: role, role: role,
phantom: PhantomData, phantom: PhantomData,
}) })
}) })
@ -391,20 +509,118 @@ impl<'d, T: Instance> Tsc<'d, T> {
config: Config, config: Config,
) -> Self { ) -> Self {
// Need to check valid pin configuration input // Need to check valid pin configuration input
Self::new_inner( let g1 = g1.filter(|b| b.check_group().is_ok());
peri, let g2 = g2.filter(|b| b.check_group().is_ok());
g1, let g3 = g3.filter(|b| b.check_group().is_ok());
g2, let g4 = g4.filter(|b| b.check_group().is_ok());
g3, let g5 = g5.filter(|b| b.check_group().is_ok());
g4, let g6 = g6.filter(|b| b.check_group().is_ok());
g5, let g7 = g7.filter(|b| b.check_group().is_ok());
g6, let g8 = g8.filter(|b| b.check_group().is_ok());
match Self::check_shields(
&g1,
&g2,
&g3,
&g4,
&g5,
&g6,
#[cfg(any(tsc_v2, tsc_v3))] #[cfg(any(tsc_v2, tsc_v3))]
g7, &g7,
#[cfg(tsc_v3)] #[cfg(tsc_v3)]
g8, &g8,
config, ) {
) Ok(()) => Self::new_inner(
peri,
g1,
g2,
g3,
g4,
g5,
g6,
#[cfg(any(tsc_v2, tsc_v3))]
g7,
#[cfg(tsc_v3)]
g8,
config,
),
Err(_) => Self::new_inner(
peri,
None,
None,
None,
None,
None,
None,
#[cfg(any(tsc_v2, tsc_v3))]
None,
#[cfg(tsc_v3)]
None,
config,
),
}
}
fn check_shields(
g1: &Option<PinGroup<'d, T, G1>>,
g2: &Option<PinGroup<'d, T, G2>>,
g3: &Option<PinGroup<'d, T, G3>>,
g4: &Option<PinGroup<'d, T, G4>>,
g5: &Option<PinGroup<'d, T, G5>>,
g6: &Option<PinGroup<'d, T, G6>>,
#[cfg(any(tsc_v2, tsc_v3))] g7: &Option<PinGroup<'d, T, G7>>,
#[cfg(tsc_v3)] g8: &Option<PinGroup<'d, T, G8>>,
) -> Result<(), GroupError> {
let mut shield_count = 0;
if let Some(pin_group) = g1 {
if pin_group.contains_shield() {
shield_count += 1;
}
};
if let Some(pin_group) = g2 {
if pin_group.contains_shield() {
shield_count += 1;
}
};
if let Some(pin_group) = g3 {
if pin_group.contains_shield() {
shield_count += 1;
}
};
if let Some(pin_group) = g4 {
if pin_group.contains_shield() {
shield_count += 1;
}
};
if let Some(pin_group) = g5 {
if pin_group.contains_shield() {
shield_count += 1;
}
};
if let Some(pin_group) = g6 {
if pin_group.contains_shield() {
shield_count += 1;
}
};
#[cfg(any(tsc_v2, tsc_v3))]
if let Some(pin_group) = g7 {
if pin_group.contains_shield() {
shield_count += 1;
}
};
#[cfg(tsc_v3)]
if let Some(pin_group) = g8 {
if pin_group.contains_shield() {
shield_count += 1;
}
};
if shield_count > 1 {
return Err(GroupError::ChannelShield);
}
Ok(())
} }
fn extract_groups(io_mask: u32) -> u32 { fn extract_groups(io_mask: u32) -> u32 {