rotary_encoder_hal/
lib.rs#![doc(html_root_url = "https://docs.rs/rotary-encoder-hal/0.5.0")]
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
use either::Either;
#[cfg(not(feature = "embedded-hal-alpha"))]
use embedded_hal::digital::v2::InputPin;
#[cfg(feature = "embedded-hal-alpha")]
use embedded_hal_alpha::digital::blocking::InputPin;
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Rotary<A, B> {
pin_a: A,
pin_b: B,
state: u8,
#[cfg(feature = "table-decoder")]
prev_next: u8,
#[cfg(feature = "table-decoder")]
store: u16,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Direction {
Clockwise,
CounterClockwise,
None,
}
#[cfg(not(feature = "table-decoder"))]
impl From<u8> for Direction {
fn from(s: u8) -> Self {
match s {
0b0001 | 0b0111 | 0b1000 | 0b1110 => Direction::Clockwise,
0b0010 | 0b0100 | 0b1011 | 0b1101 => Direction::CounterClockwise,
_ => Direction::None,
}
}
}
#[cfg(feature = "table-decoder")]
impl From<u16> for Direction {
fn from(s: u16) -> Self {
match s & 0x00ff {
0x17 => Direction::Clockwise,
0x2b => Direction::CounterClockwise,
_ => Direction::None,
}
}
}
impl<A, B> Rotary<A, B>
where
A: InputPin,
B: InputPin,
{
pub fn new(pin_a: A, pin_b: B) -> Self {
Self {
pin_a,
pin_b,
state: 0u8,
#[cfg(feature = "table-decoder")]
prev_next: 0u8,
#[cfg(feature = "table-decoder")]
store: 0u16,
}
}
#[cfg(not(feature = "table-decoder"))]
pub fn update(&mut self) -> Result<Direction, Either<A::Error, B::Error>> {
let mut s = self.state & 0b11;
#[cfg(not(feature = "embedded-hal-alpha"))]
let (a_is_low, b_is_low) = (self.pin_a.is_low(), self.pin_b.is_low());
#[cfg(feature = "embedded-hal-alpha")]
let (a_is_low, b_is_low) = (self.pin_a.is_low(), self.pin_b.is_low());
if a_is_low.map_err(Either::Left)? {
s |= 0b100;
}
if b_is_low.map_err(Either::Right)? {
s |= 0b1000;
}
self.state = s >> 2;
Ok(s.into())
}
pub fn pin_a(&mut self) -> &mut A {
&mut self.pin_a
}
pub fn pin_b(&mut self) -> &mut B {
&mut self.pin_b
}
pub fn pins(&mut self) -> (&mut A, &mut B) {
(&mut self.pin_a, &mut self.pin_b)
}
pub fn into_inner(self) -> (A, B) {
(self.pin_a, self.pin_b)
}
#[cfg(feature = "table-decoder")]
pub fn update(&mut self) -> Result<Direction, Either<A::Error, B::Error>> {
#[cfg(not(feature = "embedded-hal-alpha"))]
let (a_is_high, b_is_high) = (self.pin_a.is_high(), self.pin_b.is_high());
#[cfg(feature = "embedded-hal-alpha")]
let (a_is_high, b_is_high) = (self.pin_a.is_high(), self.pin_b.is_high());
self.prev_next <<= 2;
if a_is_high.map_err(Either::Left)? {
self.prev_next |= 0x02;
}
if b_is_high.map_err(Either::Right)? {
self.prev_next |= 0x01;
}
self.prev_next &= 0x0f;
match self.prev_next {
1 | 2 | 4 | 7 | 8 | 11 | 13 | 14 => {
self.store <<= 4;
self.store |= self.prev_next as u16;
Ok(self.store.into())
}
_ => Ok(Direction::None),
}
}
}