~ruther/avr-guess-the-number

017861cd4bf173ebad81ae71feed0ec13c36ff46 — František Boháček 2 years ago 6cb3955
feat: add button events
1 files changed, 72 insertions(+), 1 deletions(-)

M src/button.rs
M src/button.rs => src/button.rs +72 -1
@@ 8,14 8,34 @@ pub enum ButtonState {
    Released // The button was just released
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum ButtonEvent {
    Click,
    LongClick,
    LongClickContinuous,
    DoubleClick,
    None
}

const DEBOUNCECYCLES: u8 = 50;

const PRESSED_FOR_MAX: u16 = 65000;
const RELEASED_FOR_MAX: u16 = 65000;

const PRESSED_FOR_LONG: u16 = 1000;
const RELEASED_FOR_DOUBLE_CLICK: u16 = 1000;

pub struct Button {
    input: Pin<mode::Input>,
    active_high: bool,
    last_active: bool,
    active: bool,
    integrator: u8
    integrator: u8,

    pressed_for: u16,
    released_for: u16,

    last_event: ButtonEvent,
}

impl Button {


@@ 26,6 46,9 @@ impl Button {
            last_active: false,
            active: false,
            integrator: 0,
            pressed_for: 0,
            released_for: 0,
            last_event: ButtonEvent::None
        }
    }



@@ 43,7 66,55 @@ impl Button {
            self.integrator += 1;
        }

        let last_active = self.active;
        self.active = self.pressed();

        if !last_active && self.active {
            self.pressed_for = 0;
        } else if last_active && !self.active {
            self.released_for = 0;
        }

        if self.active {
            if self.pressed_for < PRESSED_FOR_MAX {
                self.pressed_for += 1;
            }
        }
        else {
            if self.released_for < RELEASED_FOR_MAX {
                self.released_for += 1;
            }
        }

        // just pressed and was released just for time it could be double click
        // fire double click right away
        // that is different to normal click. Normal clicks fire after release,
        // double click fires right after the second press
        if self.active && self.pressed_for == 1 && self.released_for < RELEASED_FOR_DOUBLE_CLICK {
            self.last_event = ButtonEvent::DoubleClick;
            self.pressed_for += 1;
        }

        // is a long click, fire event until released
        if self.active && self.pressed_for == PRESSED_FOR_LONG {
            self.last_event = ButtonEvent::LongClick;
        }
        else if self.active && self.pressed_for % PRESSED_FOR_LONG == 0 && self.last_event == ButtonEvent::None {
            self.last_event = ButtonEvent::LongClickContinuous;
        }

        // was not long click and period for double click is over
        if self.pressed_for < PRESSED_FOR_LONG && self.pressed_for > 1 && self.released_for == RELEASED_FOR_DOUBLE_CLICK {
            self.last_event = ButtonEvent::Click;
            self.released_for += 1;
        }
    }

    pub fn event(&mut self) -> ButtonEvent {
        let last_event = self.last_event;
        self.last_event = ButtonEvent::None;

        last_event
    }

    fn pressed(&mut self) -> bool{

Do not follow this link