#![no_implicit_prelude]
extern crate core;
use core::clone::Clone;
use core::cmp::{Eq, PartialEq};
use core::convert::From;
use core::fmt::{Debug, Display, Formatter, Result};
use core::marker::Copy;
use core::mem::discriminant;
use core::ops::{Deref, DerefMut};
use core::ptr::NonNull;
use crate::frame::ShiftRegister;
pub enum WakeReason {
None,
RTC,
ButtonA,
ButtonB,
ButtonC,
ButtonD,
ButtonE,
External,
}
pub struct Buttons {
sr: ShiftRegister,
state: u8,
}
pub struct ButtonsPtr(NonNull<Buttons>);
pub type Button = WakeReason;
const BUTTON_A: u8 = 0x01u8;
const BUTTON_B: u8 = 0x02u8;
const BUTTON_C: u8 = 0x04u8;
const BUTTON_D: u8 = 0x08u8;
const BUTTON_E: u8 = 0x10u8;
const BUTTON_RTC: u8 = 0x20u8;
const BUTTON_EXTERNAL: u8 = 0x40u8;
impl Buttons {
#[inline]
pub const fn raw(&self) -> u8 {
self.state
}
#[inline]
pub fn clear(&mut self) {
self.state = 0
}
#[inline]
pub fn pressed(&self) -> Button {
match self.state {
_ if self.state & BUTTON_A != 0 => Button::ButtonA,
_ if self.state & BUTTON_B != 0 => Button::ButtonB,
_ if self.state & BUTTON_C != 0 => Button::ButtonC,
_ if self.state & BUTTON_D != 0 => Button::ButtonD,
_ if self.state & BUTTON_E != 0 => Button::ButtonE,
_ if self.state & BUTTON_RTC != 0 => Button::RTC,
_ if self.state & BUTTON_EXTERNAL != 0 => Button::External,
_ => Button::None,
}
}
#[inline]
pub fn take(&mut self) -> Button {
let (m, v) = match self.state {
_ if self.state & BUTTON_A != 0 => (BUTTON_A, Button::ButtonA),
_ if self.state & BUTTON_B != 0 => (BUTTON_B, Button::ButtonB),
_ if self.state & BUTTON_C != 0 => (BUTTON_C, Button::ButtonC),
_ if self.state & BUTTON_D != 0 => (BUTTON_D, Button::ButtonD),
_ if self.state & BUTTON_E != 0 => (BUTTON_E, Button::ButtonE),
_ if self.state & BUTTON_RTC != 0 => (BUTTON_RTC, Button::RTC),
_ if self.state & BUTTON_EXTERNAL != 0 => (BUTTON_EXTERNAL, Button::External),
_ => return Button::None,
};
self.state &= !m; v
}
#[inline]
pub fn any_pressed(&self) -> bool {
self.state != 0
}
pub fn read(&mut self) -> &mut Buttons {
self.state = self.sr.read() & 0x7F; self
}
#[inline]
pub fn set_pressed(&mut self, v: Button) {
match v {
Button::None => self.state = 0u8,
Button::RTC => self.state = BUTTON_RTC,
Button::ButtonA => self.state = BUTTON_A,
Button::ButtonB => self.state = BUTTON_B,
Button::ButtonC => self.state = BUTTON_C,
Button::ButtonD => self.state = BUTTON_D,
Button::ButtonE => self.state = BUTTON_E,
Button::External => self.state = BUTTON_EXTERNAL,
}
}
#[inline]
pub fn is_pressed(&self, v: Button) -> bool {
match v {
Button::RTC if self.state & BUTTON_RTC != 0 => true,
Button::ButtonA if self.state & BUTTON_A != 0 => true,
Button::ButtonB if self.state & BUTTON_B != 0 => true,
Button::ButtonC if self.state & BUTTON_C != 0 => true,
Button::ButtonD if self.state & BUTTON_D != 0 => true,
Button::ButtonE if self.state & BUTTON_E != 0 => true,
Button::External if self.state & BUTTON_EXTERNAL != 0 => true,
_ => false,
}
}
#[inline]
pub fn shift_register(&self) -> &ShiftRegister {
&self.sr
}
#[inline]
pub(crate) fn new(state: u8, sr: ShiftRegister) -> Buttons {
Buttons { sr, state }
}
}
impl ButtonsPtr {
#[inline]
pub(crate) fn new(i: &mut Buttons) -> ButtonsPtr {
ButtonsPtr(unsafe { NonNull::new_unchecked(i) })
}
}
impl WakeReason {
#[inline]
pub fn is_none(&self) -> bool {
match self {
WakeReason::None => true,
_ => false,
}
}
#[inline]
pub fn is_some(&self) -> bool {
match self {
WakeReason::None => false,
_ => true,
}
}
#[inline]
pub fn is_button(&self) -> bool {
match self {
WakeReason::ButtonA | WakeReason::ButtonB | WakeReason::ButtonC | WakeReason::ButtonD | WakeReason::ButtonE => true,
_ => false,
}
}
#[inline]
pub fn is_trigger(&self) -> bool {
match self {
WakeReason::RTC | WakeReason::External => true,
_ => false,
}
}
#[inline]
pub fn wake_from_ext(&self) -> bool {
match self {
WakeReason::External => true,
_ => false,
}
}
#[inline]
pub fn wake_from_rtc(&self) -> bool {
match self {
WakeReason::RTC => true,
_ => false,
}
}
#[inline]
pub fn wake_from_button(&self) -> bool {
self.is_button()
}
}
impl Clone for Buttons {
#[inline]
fn clone(&self) -> Buttons {
Buttons {
sr: self.sr.clone(),
state: self.state.clone(),
}
}
}
impl Deref for ButtonsPtr {
type Target = Buttons;
#[inline]
fn deref(&self) -> &Buttons {
unsafe { self.0.as_ref() }
}
}
impl DerefMut for ButtonsPtr {
#[inline]
fn deref_mut(&mut self) -> &mut Buttons {
unsafe { self.0.as_mut() }
}
}
impl Eq for WakeReason {}
impl Copy for WakeReason {}
impl Clone for WakeReason {
#[inline]
fn clone(&self) -> WakeReason {
*self
}
}
impl From<u8> for WakeReason {
#[inline]
fn from(v: u8) -> WakeReason {
match v {
_ if v & 0x01 != 0 => WakeReason::ButtonA,
_ if v & 0x02 != 0 => WakeReason::ButtonB,
_ if v & 0x04 != 0 => WakeReason::ButtonC,
_ if v & 0x08 != 0 => WakeReason::ButtonD,
_ if v & 0x10 != 0 => WakeReason::ButtonE,
_ if v & 0x20 != 0 => WakeReason::RTC,
_ if v & 0x40 != 0 => WakeReason::External,
_ => WakeReason::None,
}
}
}
impl PartialEq for WakeReason {
#[inline]
fn eq(&self, other: &WakeReason) -> bool {
discriminant(self) == discriminant(other)
}
}
impl Debug for WakeReason {
#[cfg(feature = "debug")]
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
WakeReason::RTC => f.write_str("RTC"),
WakeReason::None => f.write_str("None"),
WakeReason::ButtonA => f.write_str("ButtonA"),
WakeReason::ButtonB => f.write_str("ButtonB"),
WakeReason::ButtonC => f.write_str("ButtonC"),
WakeReason::ButtonD => f.write_str("ButtonD"),
WakeReason::ButtonE => f.write_str("ButtonE"),
WakeReason::External => f.write_str("External"),
}
}
#[cfg(not(feature = "debug"))]
#[inline]
fn fmt(&self, _f: &mut Formatter<'_>) -> Result {
core::result::Result::Ok(())
}
}
impl Display for WakeReason {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
Debug::fmt(self, f)
}
}