]> www.fi.muni.cz Git - bike-lights.git/blob - firmware/buttons.c
buttons according to pins.txt
[bike-lights.git] / firmware / buttons.c
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <avr/sleep.h>
4
5 #include "lights.h"
6
7 static uint16_t button_start[N_BUTTONS];
8 static unsigned char button_pressed[N_BUTTONS];
9
10 static unsigned char sleep_after_release;
11
12 void init_buttons()
13 {
14         DDRB &= ~(_BV(PB4) | _BV(PB6));
15         PORTB |=  _BV(PB4) | _BV(PB6);
16
17         sleep_after_release = 0;
18         // log_byte(PORTB);
19 }
20
21 static void inline long_press(unsigned char n)
22 {
23         sleep_after_release = 1;
24         gpio_set(1, 1);
25 }
26
27 static void do_sleep()
28 {
29         // led_set_status(2);
30         // MCUCR |= _BV(ISC00); // any edge generates IRQ
31         log_byte(0xb0);
32         log_flush();
33         set_sleep_mode(SLEEP_MODE_PWR_DOWN);
34         PORTA = 0;
35         PORTB = 0;
36         DDRA = 0;
37         DDRB = 0;
38         GIMSK |= _BV(INT0); // enable INT0
39         sleep_enable();
40         sei();
41         sleep_cpu();
42         sleep_disable();
43         cli();
44         GIMSK &= ~_BV(INT0); // disable INT0
45         hw_setup();
46 }
47
48 static void inline short_press(unsigned char n)
49 {
50         led_set_status(1);
51 }
52
53 void timer_check_buttons()
54 {
55         unsigned char pinb = PINB;
56         unsigned char i;
57         unsigned char port_states[N_BUTTONS] = {
58                 pinb & _BV(PB6),
59                 pinb & _BV(PB4),
60         };
61         for (i = 0; i < N_BUTTONS; i++) {
62                 if (!port_states[i]) { // is pressed
63                         if (button_pressed[i] == 0) {
64                                 // begin of button press
65                                 button_pressed[i] = 1;
66                                 button_start[i] = jiffies;
67 #if 0
68                                 // log_byte(0xC0);
69                                 // log_word(jiffies);
70 #endif
71                         } else if (button_pressed[i] == 1) {
72                                 // been already pressed
73                                 uint16_t duration = jiffies - button_start[i];
74                                 if (duration > 80) {
75                                         // long button press
76                                         button_pressed[i] = 2;
77                                         long_press(i);
78                                 }
79                         }
80                 } else { // is not pressed
81                         if (button_pressed[i]) { // just depressed
82                                 uint16_t duration = jiffies - button_start[i];
83 #if 1
84                                 log_byte(0xC1);
85                                 log_word(duration);
86                                 log_flush();
87 #endif
88                                 button_pressed[i] = 0;
89                                 if (duration > 6 && duration < 30)
90                                         short_press(i);
91                                 if (sleep_after_release)
92                                         do_sleep();
93                         }
94                 }
95         }
96 }
97
98 ISR(INT0_vect)
99 {
100         hw_setup();
101         log_byte(0xbb);
102         log_flush();
103 }
104