From cb1ba00f0a73d426d6fd0e4a2625530535a94c24 Mon Sep 17 00:00:00 2001 From: Pavlo Tokariev Date: Wed, 18 Jan 2023 13:28:44 +0100 Subject: [PATCH 1/3] Removed keypad_new macro and implemented "new" function in the main macro with generated RefCell wrapping. --- examples/basic.rs | 10 ++-- src/lib.rs | 149 ++++++++++++++++++++++++++-------------------- 2 files changed, 90 insertions(+), 69 deletions(-) diff --git a/examples/basic.rs b/examples/basic.rs index 33bc444..dc60862 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -6,8 +6,8 @@ use core::convert::Infallible; use embedded_hal::digital::v2::InputPin; +use keypad::keypad_struct; use keypad::mock_hal::{self, GpioExt, Input, OpenDrain, Output, PullUp, GPIOA}; -use keypad::{keypad_new, keypad_struct}; // Define the struct that represents your keypad matrix. Give the specific pins // that will be used for the rows and columns of your matrix - each pin number @@ -37,21 +37,21 @@ fn main() { let pins = GPIOA::split(); // Create an instance of the keypad struct you defined above. - let keypad = keypad_new!(ExampleKeypad { - rows: ( + let keypad = ExampleKeypad::new( + ( pins.pa0.into_pull_up_input(), pins.pa1.into_pull_up_input(), pins.pa2.into_pull_up_input(), pins.pa3.into_pull_up_input(), ), - columns: ( + ( pins.pa4.into_open_drain_output(), pins.pa5.into_open_drain_output(), pins.pa6.into_open_drain_output(), pins.pa7.into_open_drain_output(), pins.pa8.into_open_drain_output(), ), - }); + ); // Create a 2d array of virtual `KeypadInput` pins, each representing 1 key in the // matrix. They implement the `InputPin` trait and can (mostly) be used diff --git a/src/lib.rs b/src/lib.rs index 6d28211..c550bdc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,21 +85,21 @@ //! let pins = GPIOA::split(); //! //! // Create an instance of the keypad struct you defined above. -//! let keypad = keypad_new!(ExampleKeypad { -//! rows: ( +//! let keypad = ExampleKeypad::new( +//! ( //! pins.pa0.into_pull_up_input(), //! pins.pa1.into_pull_up_input(), //! pins.pa2.into_pull_up_input(), //! pins.pa3.into_pull_up_input(), //! ), -//! columns: ( +//! ( //! pins.pa4.into_open_drain_output(), //! pins.pa5.into_open_drain_output(), //! pins.pa6.into_open_drain_output(), //! pins.pa7.into_open_drain_output(), //! pins.pa8.into_open_drain_output(), //! ), -//! }); +//! ); //! //! // Create a 2d array of virtual `KeypadInput` pins, each //! // representing 1 key in the matrix. They implement the @@ -330,6 +330,62 @@ macro_rules! keypad_struct { } impl $struct_name { + /// Create an instance of the struct. + /// + /// The pin numbers and modes will need to match the ones you specified with `keypad_struct!()`. + /// + /// ``` + /// # #![cfg_attr(docs_rs_workaround, feature(macro_vis_matcher))] + /// # #[macro_use] + /// # extern crate keypad; + /// # use core::convert::Infallible; + /// # use keypad::mock_hal::{self, Input, OpenDrain, Output, PullUp}; + /// # use keypad::mock_hal::{GpioExt, GPIOA}; + /// # keypad_struct!{ + /// # pub struct ExampleKeypad{ + /// # rows: ( + /// # mock_hal::gpioa::PA0>, + /// # mock_hal::gpioa::PA1>, + /// # mock_hal::gpioa::PA2>, + /// # mock_hal::gpioa::PA3>, + /// # ), + /// # columns: ( + /// # mock_hal::gpioa::PA4>, + /// # mock_hal::gpioa::PA5>, + /// # mock_hal::gpioa::PA6>, + /// # mock_hal::gpioa::PA7>, + /// # mock_hal::gpioa::PA8>, + /// # ), + /// # } + /// # } + /// # fn main() { + /// let pins = GPIOA::split(); + /// + /// let keypad = ExampleKeypad::new( + /// ( + /// pins.pa0.into_pull_up_input(), + /// pins.pa1.into_pull_up_input(), + /// pins.pa2.into_pull_up_input(), + /// pins.pa3.into_pull_up_input(), + /// ), //rows + /// ( + /// pins.pa4.into_open_drain_output(), + /// pins.pa5.into_open_drain_output(), + /// pins.pa6.into_open_drain_output(), + /// pins.pa7.into_open_drain_output(), + /// pins.pa8.into_open_drain_output(), + /// ), //columns + /// ); + /// # } + /// ``` + $visibility fn new( + rows: ($($row_type),* ,), + columns: ($($col_type),* ,),) -> Self { + Self { + rows, + columns: keypad_struct!(@refcell_tuple columns, ($($col_type),*)), + } + } /// Get a 2d array of embedded-hal input pins, each representing one /// key in the keypad matrix. #[allow(dead_code)] @@ -412,12 +468,26 @@ macro_rules! keypad_struct { nth } }; + (@destructure_ref_cell $tuple:expr, ($($repeat_n:ty),*)) => { + { + let ( + $(keypad_struct!(@underscore $repeat_n),)* + nth, ..) = $tuple; + $crate::_core::cell::RefCell::<_>::new(nth) + } + }; (@tuple_helper $tuple:expr, ($head:ty), ($($result:expr),* $(,)*)) => { [ keypad_struct!(@destructure_ref $tuple, ()), $($result),* ] }; + (@refcell_tuple_helper $tuple:expr, ($head:ty), ($($result:expr),* $(,)*)) => { + ( + keypad_struct!(@destructure_ref_cell $tuple, ()), + $($result),* + ) + }; (@tuple_helper $tuple:expr, ($head:ty $(,$repeats:ty)* $(,)*), ($($result:expr),* $(,)*)) => { keypad_struct!( @tuple_helper $tuple, ($($repeats),*), @@ -427,69 +497,20 @@ macro_rules! keypad_struct { ) ) }; + (@refcell_tuple_helper $tuple:expr, ($head:ty $(,$repeats:ty)* $(,)*), ($($result:expr),* $(,)*)) => { + keypad_struct!( + @refcell_tuple_helper $tuple, ($($repeats),*), + ( + keypad_struct!(@destructure_ref_cell $tuple, ($($repeats),*)), + $($result),* + ) + ) + }; (@tuple $tuple:expr, ($($repeats:ty),*)) => { keypad_struct!(@tuple_helper $tuple, ($($repeats),*) , ()) }; -} - -/// Create an instance of the struct you defined with the `keypad_struct!()` macro.. -/// -/// The pin numbers and modes will need to match the ones you specified with `keypad_struct!()`. -/// -/// ``` -/// # #![cfg_attr(docs_rs_workaround, feature(macro_vis_matcher))] -/// # #[macro_use] -/// # extern crate keypad; -/// # use core::convert::Infallible; -/// # use keypad::mock_hal::{self, Input, OpenDrain, Output, PullUp}; -/// # use keypad::mock_hal::{GpioExt, GPIOA}; -/// # keypad_struct!{ -/// # pub struct ExampleKeypad{ -/// # rows: ( -/// # mock_hal::gpioa::PA0>, -/// # mock_hal::gpioa::PA1>, -/// # mock_hal::gpioa::PA2>, -/// # mock_hal::gpioa::PA3>, -/// # ), -/// # columns: ( -/// # mock_hal::gpioa::PA4>, -/// # mock_hal::gpioa::PA5>, -/// # mock_hal::gpioa::PA6>, -/// # mock_hal::gpioa::PA7>, -/// # mock_hal::gpioa::PA8>, -/// # ), -/// # } -/// # } -/// # fn main() { -/// let pins = GPIOA::split(); -/// -/// let keypad = keypad_new!(ExampleKeypad { -/// rows: ( -/// pins.pa0.into_pull_up_input(), -/// pins.pa1.into_pull_up_input(), -/// pins.pa2.into_pull_up_input(), -/// pins.pa3.into_pull_up_input(), -/// ), -/// columns: ( -/// pins.pa4.into_open_drain_output(), -/// pins.pa5.into_open_drain_output(), -/// pins.pa6.into_open_drain_output(), -/// pins.pa7.into_open_drain_output(), -/// pins.pa8.into_open_drain_output(), -/// ), -/// }); -/// # } -/// ``` -#[macro_export] -macro_rules! keypad_new { - ( $struct_name:ident { - rows: ( $($row_val:expr),* $(,)* ), - columns: ( $($col_val:expr),* $(,)* ), - }) => { - $struct_name { - rows: ($($row_val),* ,), - columns: ($($crate::_core::cell::RefCell::new($col_val)),* ,), - } + (@refcell_tuple $tuple:expr, ($($repeats:ty),*)) => { + keypad_struct!(@refcell_tuple_helper $tuple, ($($repeats),*) , ()) }; } From 40edf527ec19c211fe45fff602bc72f259b62aa4 Mon Sep 17 00:00:00 2001 From: Pavlo Tokariev Date: Wed, 18 Jan 2023 14:13:05 +0100 Subject: [PATCH 2/3] Release method now returns pins without RefCells. --- src/lib.rs | 68 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c550bdc..37740e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -435,13 +435,9 @@ macro_rules! keypad_struct { /// This consumes the keypad struct. All references to its virtual /// `KeypadInput` pins must have gone out of scope before you try to /// call `.release()`, or it will fail to compile. - /// - /// The column pins will be returned inside of `RefCell`s (because - /// macros are hard). You can use `.into_inner()` to extract - /// each column pin from its `RefCell`. #[allow(dead_code)] - $visibility fn release(self) ->(($($row_type),* ,), ($($crate::_core::cell::RefCell<$col_type>),* ,)) { - (self.rows, self.columns) + $visibility fn release(self) ->(($($row_type),* ,), ($($col_type),* ,)) { + (self.rows, keypad_struct!(@de_refcell_tuple self.columns, ($($col_type),*))) } } }; @@ -468,26 +464,12 @@ macro_rules! keypad_struct { nth } }; - (@destructure_ref_cell $tuple:expr, ($($repeat_n:ty),*)) => { - { - let ( - $(keypad_struct!(@underscore $repeat_n),)* - nth, ..) = $tuple; - $crate::_core::cell::RefCell::<_>::new(nth) - } - }; (@tuple_helper $tuple:expr, ($head:ty), ($($result:expr),* $(,)*)) => { [ keypad_struct!(@destructure_ref $tuple, ()), $($result),* ] }; - (@refcell_tuple_helper $tuple:expr, ($head:ty), ($($result:expr),* $(,)*)) => { - ( - keypad_struct!(@destructure_ref_cell $tuple, ()), - $($result),* - ) - }; (@tuple_helper $tuple:expr, ($head:ty $(,$repeats:ty)* $(,)*), ($($result:expr),* $(,)*)) => { keypad_struct!( @tuple_helper $tuple, ($($repeats),*), @@ -497,6 +479,23 @@ macro_rules! keypad_struct { ) ) }; + (@tuple $tuple:expr, ($($repeats:ty),*)) => { + keypad_struct!(@tuple_helper $tuple, ($($repeats),*) , ()) + }; + (@destructure_ref_cell $tuple:expr, ($($repeat_n:ty),*)) => { + { + let ( + $(keypad_struct!(@underscore $repeat_n),)* + nth, ..) = $tuple; + $crate::_core::cell::RefCell::<_>::new(nth) + } + }; + (@refcell_tuple_helper $tuple:expr, ($head:ty), ($($result:expr),* $(,)*)) => { + ( + keypad_struct!(@destructure_ref_cell $tuple, ()), + $($result),* + ) + }; (@refcell_tuple_helper $tuple:expr, ($head:ty $(,$repeats:ty)* $(,)*), ($($result:expr),* $(,)*)) => { keypad_struct!( @refcell_tuple_helper $tuple, ($($repeats),*), @@ -506,12 +505,35 @@ macro_rules! keypad_struct { ) ) }; - (@tuple $tuple:expr, ($($repeats:ty),*)) => { - keypad_struct!(@tuple_helper $tuple, ($($repeats),*) , ()) - }; (@refcell_tuple $tuple:expr, ($($repeats:ty),*)) => { keypad_struct!(@refcell_tuple_helper $tuple, ($($repeats),*) , ()) }; + (@destructure_de_ref_cell $tuple:expr, ($($repeat_n:ty),*)) => { + { + let ( + $(keypad_struct!(@underscore $repeat_n),)* + nth, ..) = $tuple; + nth.into_inner() + } + }; + (@de_refcell_tuple_helper $tuple:expr, ($head:ty), ($($result:expr),* $(,)*)) => { + ( + keypad_struct!(@destructure_de_ref_cell $tuple, ()), + $($result),* + ) + }; + (@de_refcell_tuple_helper $tuple:expr, ($head:ty $(,$repeats:ty)* $(,)*), ($($result:expr),* $(,)*)) => { + keypad_struct!( + @de_refcell_tuple_helper $tuple, ($($repeats),*), + ( + keypad_struct!(@destructure_de_ref_cell $tuple, ($($repeats),*)), + $($result),* + ) + ) + }; + (@de_refcell_tuple $tuple:expr, ($($repeats:ty),*)) => { + keypad_struct!(@de_refcell_tuple_helper $tuple, ($($repeats),*) , ()) + }; } #[cfg(feature = "example_generated")] From 166c6a1372051dac47c169c7554ed4e3113fe7b0 Mon Sep 17 00:00:00 2001 From: Pavlo Tokariev Date: Wed, 18 Jan 2023 14:19:59 +0100 Subject: [PATCH 3/3] Removed keypad_new mentions. --- README.md | 14 +++++++------- src/lib.rs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ed43992..e768a99 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ For an example that runs on an actual microcontroller, see use core::convert::Infallible; use embedded_hal::digital::v2::InputPin; use keypad::mock_hal::{self, GpioExt, Input, OpenDrain, Output, PullUp, GPIOA}; -use keypad::{keypad_new, keypad_struct}; +use keypad::keypad_struct; // Define the struct that represents your keypad matrix circuit, // picking the row and column pin numbers. @@ -88,21 +88,21 @@ fn main() { let pins = GPIOA::split(); // Create an instance of the keypad struct you defined above. - let keypad = keypad_new!(ExampleKeypad { - rows: ( + let keypad = ExampleKeypad::new( + ( pins.pa0.into_pull_up_input(), pins.pa1.into_pull_up_input(), pins.pa2.into_pull_up_input(), pins.pa3.into_pull_up_input(), - ), - columns: ( + ), // rows + ( pins.pa4.into_open_drain_output(), pins.pa5.into_open_drain_output(), pins.pa6.into_open_drain_output(), pins.pa7.into_open_drain_output(), pins.pa8.into_open_drain_output(), - ), - }); + ), // columns + ); // Create a 2d array of virtual `KeypadInput` pins, each representing 1 key // in the matrix. They implement the `InputPin` trait and can (mostly) be diff --git a/src/lib.rs b/src/lib.rs index 37740e5..f9637cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -367,14 +367,14 @@ macro_rules! keypad_struct { /// pins.pa1.into_pull_up_input(), /// pins.pa2.into_pull_up_input(), /// pins.pa3.into_pull_up_input(), - /// ), //rows + /// ), // rows /// ( /// pins.pa4.into_open_drain_output(), /// pins.pa5.into_open_drain_output(), /// pins.pa6.into_open_drain_output(), /// pins.pa7.into_open_drain_output(), /// pins.pa8.into_open_drain_output(), - /// ), //columns + /// ), // columns /// ); /// # } /// ```