Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ergonomics improvements (keypad_new and RefCell in release are no more) #5

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
10 changes: 5 additions & 5 deletions examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
181 changes: 112 additions & 69 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<Error = Infallible>{
/// # rows: (
/// # mock_hal::gpioa::PA0<Input<PullUp>>,
/// # mock_hal::gpioa::PA1<Input<PullUp>>,
/// # mock_hal::gpioa::PA2<Input<PullUp>>,
/// # mock_hal::gpioa::PA3<Input<PullUp>>,
/// # ),
/// # columns: (
/// # mock_hal::gpioa::PA4<Output<OpenDrain>>,
/// # mock_hal::gpioa::PA5<Output<OpenDrain>>,
/// # mock_hal::gpioa::PA6<Output<OpenDrain>>,
/// # mock_hal::gpioa::PA7<Output<OpenDrain>>,
/// # mock_hal::gpioa::PA8<Output<OpenDrain>>,
/// # ),
/// # }
/// # }
/// # 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)]
Expand Down Expand Up @@ -379,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),*)))
}
}
};
Expand Down Expand Up @@ -430,67 +482,58 @@ macro_rules! keypad_struct {
(@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<Error = Infallible>{
/// # rows: (
/// # mock_hal::gpioa::PA0<Input<PullUp>>,
/// # mock_hal::gpioa::PA1<Input<PullUp>>,
/// # mock_hal::gpioa::PA2<Input<PullUp>>,
/// # mock_hal::gpioa::PA3<Input<PullUp>>,
/// # ),
/// # columns: (
/// # mock_hal::gpioa::PA4<Output<OpenDrain>>,
/// # mock_hal::gpioa::PA5<Output<OpenDrain>>,
/// # mock_hal::gpioa::PA6<Output<OpenDrain>>,
/// # mock_hal::gpioa::PA7<Output<OpenDrain>>,
/// # mock_hal::gpioa::PA8<Output<OpenDrain>>,
/// # ),
/// # }
/// # }
/// # 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)),* ,),
(@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),*),
(
keypad_struct!(@destructure_ref_cell $tuple, ($($repeats),*)),
$($result),*
)
)
};
(@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")]
Expand Down