X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=tinyboard.git;a=blobdiff_plain;f=projects%2Fstep-up%2Fbuttons.c;fp=projects%2Fstep-up%2Fbuttons.c;h=4101a2f5885c3920c76a7b6568dbcfa3db8fd789;hp=0000000000000000000000000000000000000000;hb=287f589eb6aee0d3aa9726106c6782c41c81ec6a;hpb=887aa3ba899b44aa07cfabfab4ce3495074f0788 diff --git a/projects/step-up/buttons.c b/projects/step-up/buttons.c new file mode 100644 index 0000000..4101a2f --- /dev/null +++ b/projects/step-up/buttons.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include // for NULL + +#include "lights.h" + +#define WAKEUP_LIMIT 5 // times 100 ms +#define SHORT_PRESS_MIN 10 // in jiffies (100 Hz ticks) +#define SHORT_PRESS_MAX 50 +#define LONG_PRESS_MIN 100 +static uint16_t button_start; +static unsigned char prev_state; + +void status_led_on_off(unsigned char mode) +{ + if (mode) + PORTB |= _BV(PORTB0); + else + PORTB &= ~_BV(PORTB0); +} + +void init_buttons() +{ + DDRB &= ~_BV(DDB1); + DDRB |= _BV(DDB0); + PORTB |= _BV(PORTB1); // enable internal pull-up + PORTB &= ~_BV(PORTB0); // status led off + GIMSK &= ~_BV(PCIE); // disable pin-change IRQs + PCMSK = 0; // disable pin-change IRQs on all pins of port B + + button_start = 0; + prev_state = 0; +} + +void susp_buttons() +{ + DDRB &= ~(_BV(DDB1)); // set as input + PORTB |= _BV(PORTB1); // enable internal pull-up + PORTB &= ~_BV(PORTB0); // set to zero + + GIMSK |= _BV(PCIE); + + PCMSK = _BV(PCINT1); + // disable pin-change IRQs on all pins except PB1 +} + +void timer_check_buttons() +{ + unsigned char cur = !(PINB & _BV(PINB1)); + unsigned char prev = prev_state; + + prev_state = cur; + + if (cur && !prev) { // --- just pressed --- + button_start = jiffies; + // set_status_led(button, NULL); + + } else if (cur && prev) { // --- is still pressed --- + uint16_t duration = jiffies - button_start; + + if (duration > LONG_PRESS_MIN) { + long_press_start(); + // acknowledge long press + } + } else if (!cur && prev) { // --- just released --- + uint16_t duration = jiffies - button_start; + + if (duration > SHORT_PRESS_MIN && duration < SHORT_PRESS_MAX) { + short_press(); + } else if (duration > LONG_PRESS_MIN) { + // set_status_led(button, NULL); + long_press(); + } + // ignore other button-press durations + } +} + +#if 0 +static void handle_brake(unsigned char cur, unsigned char prev) +{ + if (cur && !prev) { // --- just pressed --- + button_start[2] = jiffies; + } else if (!cur && prev) { // --- just released --- + button_start[2] = jiffies; + } else { // --- no change --- + uint16_t duration = jiffies - button_start[2]; + + if (duration > 6) { + if (cur) { + if (button_state.brake_working + && !button_state.brake_reported) { + button_state.brake_reported = 1; + brake_on(); + } + } else { + button_state.brake_working = 1; + if (button_state.brake_reported) { + button_state.brake_reported = 0; + brake_off(); + } + } + button_start[2] = jiffies - 7; // avoid overflow + } + } +} +#endif + +unsigned char buttons_wait_for_release() +{ + uint16_t wake_count = 0; + unsigned char pin; + + do { + if (wake_count++ > WAKEUP_LIMIT) + status_led_on_off(1); // inform the user + + _delay_ms(100); + + pin = PINB & _BV(PINB1); + } while (!(pin & _BV(PINB1))); + + status_led_on_off(0); + + return wake_count > WAKEUP_LIMIT; +} + +ISR(PCINT0_vect) +{ + // empty - let it wake us from sleep, but do nothing else +} +