]> www.fi.muni.cz Git - tinyboard.git/blobdiff - projects/step-up/buttons.c
Added missing source files battery.c and buttons.c
[tinyboard.git] / projects / step-up / buttons.c
diff --git a/projects/step-up/buttons.c b/projects/step-up/buttons.c
new file mode 100644 (file)
index 0000000..4101a2f
--- /dev/null
@@ -0,0 +1,133 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include <stdlib.h> // 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
+}
+