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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//! Support for hardware buttons.
//!
//! # Scope
//!
//! This module provides:
//! - a lower-level interface for reading a button or switch's state
//! - optional 'debouncing'
//! - a higher-level interface for retrieving button events, including:
//!   - simple 'click' events
//!   - support for treating two buttons as a single device, with a 'clicked
//!     both' event
//!   - support for detecting 'hold' (long press) events
//! - convenience APIs for using these features with the built-in buttons
//!
//! # Polling model
//!
//! This module's client is responsible for calling polling functions at
//! regular intervals (nothing in this module itself uses interrupts or
//! timers).
//!
//! The intended polling interval is 6ms.
//!
//! In practice it appears no debouncing is needed for the micro:bit's
//! built-in buttons given this polling interval, so by default no debouncing
//! is applied.
//!
//! With a 6ms polling interval, the 'with hold' drivers report a hold event
//! after a press 1.5s long.
//!
//! # Usage
//!
//! The simplest way to access the higher-level features is via one of the
//! high-level driver modules:
//! - [`single_eager`]
//! - [`single_lazy`]
//! - [`single_with_hold`]
//! - [`dual`]
//! - [`dual_with_hold`]
//!
//! Each of these modules defines a similar interface, including a
//! `ButtonEvent` enum and either a `Monitor` type for each button or a
//! `Monitor` type for both buttons treated as a single device.
//!
//! Each `Monitor` type defines a `new()` method which expects a [`ButtonA`],
//! a [`ButtonB`], or one of each.
//!
//! Use the [`from_pins()`] function to retrieve [`ButtonA`] and [`ButtonB`].
//!
//! Each `Monitor` type defines a `poll()` method which returns an
//! `Option(ButtonEvent)`; this method should be called at regular intervals
//! (in practice every 6ms).
//!
//! ## Lower-level access
//!
//! See the [`core`] module if none of the event types above are suitable for
//! your purposes, or to use an external button.
//!
//! See the [`debouncing`] module if you need to control debouncing behaviour.
//!
//! # Examples
//!
//! ```ignore
//! use rmicrobit::prelude::*;
//! use rmicrobit::gpio::PinsByKind;
//! use rmicrobit::buttons;
//! use rmicrobit::buttons::dual::{ABMonitor, ButtonEvent};
//! let p: nrf51::Peripherals = _;
//! let PinsByKind {button_pins, ..} = p.GPIO.split_by_kind();
//! let (button_a, button_b) = buttons::from_pins(button_pins);
//! let monitor = ABMonitor::new(button_a, button_b);
//! loop {
//!     // every 6ms
//!     match monitor.poll() {
//!         Some(ButtonEvent::ClickA) => { ... }
//!         Some(ButtonEvent::ClickB) => { ... }
//!         Some(ButtonEvent::ClickAB) => { ... }
//!         None => {}
//!     }
//! }
//! ```
//!
//! See `examples/use_single_button_monitor.rs` and
//! `examples/use_dual_button_monitor.rs` for complete examples.
//!
//! [`single_eager`]: crate::buttons::single_eager
//! [`single_lazy`]: crate::buttons::single_lazy
//! [`single_with_hold`]: crate::buttons::single_with_hold
//! [`dual`]: crate::buttons::dual
//! [`dual_with_hold`]: crate::buttons::dual_with_hold
//! [`from_pins()`]: crate::buttons::from_pins
//! [`ButtonA`]: crate::buttons::builtin::ButtonA
//! [`ButtonB`]: crate::buttons::builtin::ButtonB

pub use crate::buttons::builtin::from_pins;

pub mod builtin;
pub mod core;
pub mod debouncing;

/// Implementations of the high-level button drivers.
pub mod monitors {
    pub mod holding;
    pub mod single;
    pub mod dual;
    pub mod single_with_hold;
    pub mod dual_with_hold;
}


/// High-level driver for a single button, with events on press.
pub mod single_eager {
    pub use crate::buttons::monitors::single::Event as ButtonEvent;
    pub use crate::buttons::builtin::{
        EagerButtonAMonitor as ButtonAMonitor,
        EagerButtonBMonitor as ButtonBMonitor,
    };
}

/// High-level driver for a single button, with events on release.
pub mod single_lazy {
    pub use crate::buttons::monitors::single::Event as ButtonEvent;
    pub use crate::buttons::builtin::{
        LazyButtonAMonitor as ButtonAMonitor,
        LazyButtonBMonitor as ButtonBMonitor,
    };
}

/// High-level driver for two buttons together.
pub mod dual {
    pub use crate::buttons::monitors::dual::Event as ButtonEvent;
    pub use crate::buttons::builtin::{
        ABMonitor,
    };
}

/// High-level driver for a single button, with 'hold' support.
pub mod single_with_hold {
    pub use crate::buttons::monitors::single_with_hold::Event as ButtonEvent;
    pub use crate::buttons::builtin::{
        ButtonAMonitorWithHold as ButtonAMonitor,
        ButtonBMonitorWithHold as ButtonBMonitor,
    };
}


/// High-level driver for two buttons together, with 'hold' support.
pub mod dual_with_hold {
    pub use crate::buttons::monitors::dual_with_hold::Event as ButtonEvent;
    pub use crate::buttons::builtin::{
        ABMonitorWithHold as ABMonitor,
    };
}