#![allow(missing_docs)] use embedded_hal::digital::v2::{InputPin, OutputPin}; use generic_array::{ArrayLength, GenericArray}; use heapless::Vec; pub trait HeterogenousArray { type Len; } /// Macro to implement a iterator on trait objects from a tuple struct. #[macro_export] macro_rules! impl_heterogenous_array { ($s:ident, $t:ty, $len:tt, [$($idx:tt),+]) => { impl<'a> IntoIterator for &'a $s { type Item = &'a $t; type IntoIter = generic_array::GenericArrayIter<&'a $t, $len>; fn into_iter(self) -> Self::IntoIter { self.as_array().into_iter() } } impl<'a> IntoIterator for &'a mut $s { type Item = &'a mut $t; type IntoIter = generic_array::GenericArrayIter<&'a mut $t, $len>; fn into_iter(self) -> Self::IntoIter { self.as_mut_array().into_iter() } } impl $crate::matrix::HeterogenousArray for $s { type Len = $len; } impl $s { pub fn as_array(&self) -> generic_array::GenericArray<&$t, $len> { generic_array::arr![&$t; $( &self.$idx as &$t, )+] } pub fn as_mut_array(&mut self) -> generic_array::GenericArray<&mut $t, $len> { generic_array::arr![&mut $t; $( &mut self.$idx as &mut $t, )+] } } } } pub struct Matrix { cols: C, rows: R, } impl Matrix { pub fn new(cols: C, rows: R) -> Result where for<'a> &'a mut R: IntoIterator>, { let mut res = Self { cols, rows }; res.clear()?; Ok(res) } pub fn clear<'a, E: 'a>(&'a mut self) -> Result<(), E> where &'a mut R: IntoIterator>, { for r in self.rows.into_iter() { r.set_high()?; } Ok(()) } pub fn get<'a, E: 'a>(&'a mut self) -> Result, E> where &'a mut R: IntoIterator>, R: HeterogenousArray, R::Len: ArrayLength>, &'a C: IntoIterator>, C: HeterogenousArray, C::Len: ArrayLength, { let cols = &self.cols; self.rows .into_iter() .map(|r| { r.set_low()?; let col = cols .into_iter() .map(|c| c.is_low()) .collect::, E>>()? .into_iter() .collect(); r.set_high()?; Ok(col) }) .collect::, E>>() .map(|res| PressedKeys(res.into_iter().collect())) } } #[derive(Default, PartialEq, Eq)] pub struct PressedKeys(pub GenericArray, U>) where V: ArrayLength, U: ArrayLength>; impl PressedKeys where V: ArrayLength, U: ArrayLength>, { pub fn iter_pressed<'a>(&'a self) -> impl Iterator + Clone + 'a { self.0.iter().enumerate().flat_map(|(i, r)| { r.iter() .enumerate() .filter_map(move |(j, &b)| if b { Some((i, j)) } else { None }) }) } } impl<'a, U, V> IntoIterator for &'a PressedKeys where V: ArrayLength, U: ArrayLength>, U: ArrayLength<&'a GenericArray>, { type IntoIter = core::slice::Iter<'a, GenericArray>; type Item = &'a GenericArray; fn into_iter(self) -> Self::IntoIter { self.0.iter() } }