1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#![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<C, R> {
    cols: C,
    rows: R,
}

impl<C, R> Matrix<C, R> {
    pub fn new<E>(cols: C, rows: R) -> Result<Self, E>
    where
        for<'a> &'a mut R: IntoIterator<Item = &'a mut dyn OutputPin<Error = E>>,
    {
        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<Item = &'a mut dyn OutputPin<Error = E>>,
    {
        for r in self.rows.into_iter() {
            r.set_high()?;
        }
        Ok(())
    }
    pub fn get<'a, E: 'a>(&'a mut self) -> Result<PressedKeys<R::Len, C::Len>, E>
    where
        &'a mut R: IntoIterator<Item = &'a mut dyn OutputPin<Error = E>>,
        R: HeterogenousArray,
        R::Len: ArrayLength<GenericArray<bool, C::Len>>,
        &'a C: IntoIterator<Item = &'a dyn InputPin<Error = E>>,
        C: HeterogenousArray,
        C::Len: ArrayLength<bool>,
    {
        let cols = &self.cols;
        self.rows
            .into_iter()
            .map(|r| {
                r.set_low()?;
                let col = cols
                    .into_iter()
                    .map(|c| c.is_low())
                    .collect::<Result<Vec<_, C::Len>, E>>()?
                    .into_iter()
                    .collect();
                r.set_high()?;
                Ok(col)
            })
            .collect::<Result<Vec<_, R::Len>, E>>()
            .map(|res| PressedKeys(res.into_iter().collect()))
    }
}

#[derive(Default, PartialEq, Eq)]
pub struct PressedKeys<U, V>(pub GenericArray<GenericArray<bool, V>, U>)
where
    V: ArrayLength<bool>,
    U: ArrayLength<GenericArray<bool, V>>;

impl<U, V> PressedKeys<U, V>
where
    V: ArrayLength<bool>,
    U: ArrayLength<GenericArray<bool, V>>,
{
    pub fn iter_pressed<'a>(&'a self) -> impl Iterator<Item = (usize, usize)> + 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<U, V>
where
    V: ArrayLength<bool>,
    U: ArrayLength<GenericArray<bool, V>>,
    U: ArrayLength<&'a GenericArray<bool, V>>,
{
    type IntoIter = core::slice::Iter<'a, GenericArray<bool, V>>;
    type Item = &'a GenericArray<bool, V>;
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}