#![no_std]
#![warn(missing_docs)]
extern crate embedded_hal;
use embedded_hal::Qei;
const THRESHOLD: u16 = 32768;
#[derive(Debug)]
pub enum SamplingError {
SampleTooFar,
}
#[derive(Debug)]
pub struct QeiManager<T> {
counter: i64,
previous_count: u16,
qei: T,
}
impl<T, K> QeiManager<T>
where
T: Qei<Count = K>,
K: Into<u16>,
{
pub fn new(qei: T) -> QeiManager<T> {
QeiManager {
counter: 0,
previous_count: 0,
qei,
}
}
pub fn sample(&mut self) -> Result<(), SamplingError> {
let count = self.qei.count().into();
self.update(count)
}
pub fn sample_unwrap(&mut self) {
let count = self.qei.count().into();
self.update(count).unwrap();
}
#[allow(dead_code)]
pub(crate) fn update_unwrap(&mut self, current_count: u16) {
self.update(current_count).unwrap();
}
pub(crate) fn update(&mut self, current_count: u16) -> Result<(), SamplingError> {
if current_count == self.previous_count {
return Ok(());
} else if self.previous_count < current_count {
if current_count - self.previous_count < THRESHOLD {
self.counter += (current_count - self.previous_count) as i64;
} else if current_count - self.previous_count > THRESHOLD {
self.counter -= (u16::max_value() - current_count + self.previous_count + 1) as i64;
} else {
return Err(SamplingError::SampleTooFar);
}
} else {
if self.previous_count - current_count < THRESHOLD {
self.counter -= (self.previous_count - current_count) as i64;
} else if self.previous_count - current_count > THRESHOLD {
self.counter += (u16::max_value() - self.previous_count + current_count + 1) as i64;
} else {
return Err(SamplingError::SampleTooFar);
}
}
self.previous_count = current_count;
Ok(())
}
pub fn count(&self) -> i64 {
self.counter
}
pub fn reset(&mut self) {
self.counter = 0;
}
}
#[cfg(test)]
mod test {
use embedded_hal::{Direction, Qei};
use QeiManager;
struct DummyQei {}
impl Qei for DummyQei {
type Count = u16;
fn count(&self) -> u16 {
0
}
fn direction(&self) -> Direction {
Direction::Downcounting
}
}
#[test]
fn no_trap() {
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(55);
assert_eq!(qei.count(), 55)
}
#[test]
fn underflow() {
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(5);
qei.update_unwrap(65532);
assert_eq!(qei.count(), -4); let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(5);
qei.update_unwrap(65535);
assert_eq!(qei.count(), -1);
}
#[test]
fn overflow() {
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(65522);
qei.update_unwrap(55);
assert_eq!(qei.count(), 55_i64);
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(65535);
qei.update_unwrap(0);
assert_eq!(qei.count(), 0);
qei.update_unwrap(65535);
qei.update_unwrap(1);
assert_eq!(qei.count(), 1);
}
#[test]
fn middle_values() {
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(13546);
qei.update_unwrap(13500);
qei.update_unwrap(15678);
assert_eq!(qei.count(), 15678);
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(16000);
qei.update_unwrap(15000);
assert_eq!(qei.count(), 15000);
}
#[test]
fn going_back() {
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(65489);
qei.update_unwrap(65000);
assert_eq!(qei.count(), -536); qei.update_unwrap(63000);
assert_eq!(qei.count(), -2536); qei.update_unwrap(62999);
assert_eq!(qei.count(), -2537); }
#[test]
fn no_changes() {
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(0);
qei.update_unwrap(0);
assert_eq!(qei.count(), 0);
}
#[test]
fn small_changes() {
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(0);
qei.update_unwrap(u16::max_value());
assert_eq!(qei.count(), -1);
let mut qei = QeiManager::new(DummyQei {});
qei.update_unwrap(u16::max_value());
qei.update_unwrap(0);
assert_eq!(qei.count(), 0);
qei.update_unwrap(1);
assert_eq!(qei.count(), 1);
qei.update_unwrap(65535);
assert_eq!(qei.count(), -1);
qei.update_unwrap(65534);
assert_eq!(qei.count(), -2);
}
}