#[derive(Debug, Clone)]
pub struct EncoderAccel {
last_detent_ms: u32,
initialized: bool,
}
impl Default for EncoderAccel {
fn default() -> Self {
Self::new()
}
}
impl EncoderAccel {
pub fn new() -> Self {
Self {
last_detent_ms: 0,
initialized: false,
}
}
pub fn steps(&mut self, now_ms: u32) -> u8 {
if !self.initialized {
self.last_detent_ms = now_ms;
self.initialized = true;
return 1;
}
let interval_ms = now_ms.wrapping_sub(self.last_detent_ms);
self.last_detent_ms = now_ms;
accel_curve(interval_ms)
}
pub fn reset(&mut self) {
self.initialized = false;
}
}
fn accel_curve(interval_ms: u32) -> u8 {
if interval_ms < 20 {
8 } else if interval_ms < 50 {
4 } else if interval_ms < 100 {
2 } else {
1 }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn first_detent_always_one_step() {
let mut enc = EncoderAccel::new();
assert_eq!(enc.steps(1000), 1);
}
#[test]
fn slow_turn_gives_one_step() {
let mut enc = EncoderAccel::new();
enc.steps(0);
assert_eq!(enc.steps(200), 1);
assert_eq!(enc.steps(500), 1);
}
#[test]
fn moderate_turn_gives_two_steps() {
let mut enc = EncoderAccel::new();
enc.steps(0);
assert_eq!(enc.steps(80), 2);
assert_eq!(enc.steps(150), 2); }
#[test]
fn fast_turn_gives_four_steps() {
let mut enc = EncoderAccel::new();
enc.steps(0);
assert_eq!(enc.steps(30), 4);
}
#[test]
fn very_fast_turn_gives_eight_steps() {
let mut enc = EncoderAccel::new();
enc.steps(0);
assert_eq!(enc.steps(10), 8);
assert_eq!(enc.steps(15), 8); }
#[test]
fn reset_makes_next_return_one() {
let mut enc = EncoderAccel::new();
enc.steps(0);
enc.steps(10); enc.reset();
assert_eq!(enc.steps(20), 1); }
#[test]
fn acceleration_slows_down() {
let mut enc = EncoderAccel::new();
enc.steps(0);
assert_eq!(enc.steps(10), 8); assert_eq!(enc.steps(110), 1); }
#[test]
fn wrapping_timestamp() {
let mut enc = EncoderAccel::new();
enc.steps(u32::MAX - 10);
assert_eq!(enc.steps(9), 4); }
}