2020-06-19 18:03:43 +00:00
|
|
|
use crate::Register;
|
2017-12-13 13:28:11 +00:00
|
|
|
|
2018-11-05 10:05:34 +00:00
|
|
|
/// Represents whether a pin is an input or an output.
|
2017-12-13 13:28:11 +00:00
|
|
|
pub enum DataDirection {
|
2018-11-05 10:05:34 +00:00
|
|
|
/// The pin is exclusively used for reading signals.
|
2017-12-13 13:28:11 +00:00
|
|
|
Input,
|
2018-11-05 10:05:34 +00:00
|
|
|
/// The pin is exclusively used for sending signals.
|
2017-12-13 13:28:11 +00:00
|
|
|
Output,
|
|
|
|
}
|
2017-08-29 13:48:44 +00:00
|
|
|
|
|
|
|
/// An IO pin.
|
|
|
|
pub trait Pin {
|
2017-09-23 04:44:02 +00:00
|
|
|
/// The associated data direction register.
|
2017-12-13 13:13:24 +00:00
|
|
|
type DDR: Register<T=u8>;
|
2017-08-29 13:48:44 +00:00
|
|
|
/// The associated port register.
|
2017-12-13 13:13:24 +00:00
|
|
|
type PORT: Register<T=u8>;
|
2018-11-05 10:05:34 +00:00
|
|
|
|
2017-08-29 13:48:44 +00:00
|
|
|
///
|
|
|
|
/// Reads from the register will read input bits.
|
|
|
|
/// Writes to the register will toggle bits.
|
2017-12-13 13:13:24 +00:00
|
|
|
type PIN: Register<T=u8>;
|
2017-08-29 13:48:44 +00:00
|
|
|
/// The mask of the pin used for accessing registers.
|
|
|
|
const MASK: u8;
|
|
|
|
|
|
|
|
/// Sets the data direction of the pin.
|
|
|
|
#[inline(always)]
|
|
|
|
fn set_direction(direction: DataDirection) {
|
|
|
|
match direction {
|
|
|
|
DataDirection::Input => Self::set_input(),
|
|
|
|
DataDirection::Output => Self::set_output(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the pin up as an input.
|
|
|
|
#[inline(always)]
|
|
|
|
fn set_input() {
|
2018-11-05 10:05:34 +00:00
|
|
|
Self::DDR::unset_mask_raw(Self::MASK);
|
2017-08-29 13:48:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the pin up as an output.
|
|
|
|
#[inline(always)]
|
|
|
|
fn set_output() {
|
2018-11-05 10:05:34 +00:00
|
|
|
Self::DDR::set_mask_raw(Self::MASK);
|
2017-08-29 13:48:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Set the pin to high.
|
|
|
|
///
|
|
|
|
/// The pin must be configured as an output.
|
|
|
|
#[inline(always)]
|
|
|
|
fn set_high() {
|
2018-11-05 10:05:34 +00:00
|
|
|
Self::PORT::set_mask_raw(Self::MASK);
|
2017-08-29 13:48:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Set the pin to low.
|
|
|
|
///
|
|
|
|
/// The pin must be configured as an output.
|
|
|
|
#[inline(always)]
|
|
|
|
fn set_low() {
|
2018-11-05 10:05:34 +00:00
|
|
|
Self::PORT::unset_mask_raw(Self::MASK);
|
2017-08-29 13:48:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Toggles the pin.
|
|
|
|
///
|
|
|
|
/// The pin must be configured as an output.
|
|
|
|
#[inline(always)]
|
|
|
|
fn toggle() {
|
|
|
|
// FIXME: We can optimise this on post-2006 AVRs.
|
|
|
|
// http://www.avrfreaks.net/forum/toggle-state-output-pin
|
|
|
|
// set(Self::PIN, Self::MASK);
|
2017-12-13 09:17:28 +00:00
|
|
|
Self::PORT::toggle_raw(Self::MASK);
|
2017-08-29 13:48:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Check if the pin is currently high.
|
|
|
|
///
|
|
|
|
/// The pin must be configured as an input.
|
|
|
|
#[inline(always)]
|
|
|
|
fn is_high() -> bool {
|
2018-11-05 10:05:34 +00:00
|
|
|
Self::PIN::is_mask_set_raw(Self::MASK)
|
2017-08-29 13:48:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks if the pin is currently low.
|
|
|
|
///
|
|
|
|
/// The pin must be configured as an input.
|
|
|
|
#[inline(always)]
|
|
|
|
fn is_low() -> bool {
|
2017-12-13 09:17:28 +00:00
|
|
|
Self::PIN::is_clear_raw(Self::MASK)
|
2017-08-29 13:48:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|