]> www.fi.muni.cz Git - bike-lights.git/blob - firmware/buttons.c
firmware: buttons-press and pwrdown rework
[bike-lights.git] / firmware / buttons.c
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <avr/sleep.h>
4 #include <util/delay.h>
5
6 #include "lights.h"
7
8 static uint16_t button_start[N_BUTTONS];
9 static unsigned char prev_pin;
10
11 static unsigned char user_params[MAX_USER_PARAMS] = { 0, 0, 0 };
12 static unsigned char user_params_max[MAX_USER_PARAMS] = { 3, 2, 2 };
13
14 static unsigned char user_params_state = 0;
15         /*
16          * Here 0 means "no setup currently in progress",
17          * 1 .. MAX_USER_PARAMS means "now short presses increase or decrease
18          *           the value of user_params[user_params_state-1]"
19          */
20
21 static uint16_t user_params_starttime;
22
23 static void toggle_bright_mode()
24 {
25         // TODO
26 }
27
28 static void set_panic_mode()
29 {
30         // TODO
31 }
32
33 unsigned char get_user_param(unsigned char param)
34 {
35         if (param < MAX_USER_PARAMS)
36                 return user_params[param];
37         return 0; // FIXME: internal error?
38 }
39
40 static inline void short_press(unsigned char button)
41 {
42         unsigned char param;
43
44         if (user_params_state == 0) {
45                 if (button == 0)
46                         toggle_bright_mode();
47                 else
48                         set_panic_mode();
49                 return;
50         }
51
52         param = user_params_state-1;
53
54         if (button == 0) {
55                 if (user_params[param])
56                         user_params[param]--;
57                 else
58                         user_params[param] = user_params_max[param];
59         } else {
60                 user_params[param]++;
61
62                 if (user_params[param] >= user_params_max[param])
63                         user_params[param] = 0;
64         }
65         // FIXME: notify somebody about user_params change?
66
67         // set_status_led(2, user_params[param]);
68
69         user_params_starttime = jiffies;
70 }
71
72 static inline void long_press(unsigned char button)
73 {
74         if (button == 0) {
75                 power_down();
76                 return;
77         }
78
79         // button 1 - cycle through states
80         user_params_state++;
81
82         if (user_params_state >= MAX_USER_PARAMS)
83                 user_params_state = 1;
84
85         // set_status_led(1, state);
86         user_params_starttime = jiffies;
87 }
88
89 void init_buttons()
90 {
91         unsigned char i;
92
93         DDRA &= ~(_BV(PA3) | _BV(PA4));
94         PORTA |=  _BV(PA3) | _BV(PA4);
95
96         button_start[0] = 0;
97         button_start[1] = 0;
98         prev_pin = _BV(PA3) | _BV(PA4);
99 }
100
101 void timer_check_buttons()
102 {
103         unsigned char pin = PINA & (_BV(PA3) | _BV(PA4));
104
105         handle_button(0, pin & _BV(PA3), prev_pin & _BV(PA3));
106         handle_button(1, pin & _BV(PA4), prev_pin & _BV(PA4));
107
108         prev_pin = pin;
109
110         if (jiffies - user_params_starttime > 500) {
111                 user_params_state = 0;
112                 // set_status_led(0, idle);
113                 // set_status_led(1, idle);
114         }
115 }
116
117 static void handle_button(unsigned char button, unsigned char cur,
118         unsigned char prev)
119 {
120         // BEWARE: pins are at _zero_ when pressed!
121         if (!cur && prev) {                   // --- just pressed ---
122                 button_start[i] = jiffies;
123                 // set_status_led(button, 0);
124
125         } else if (!cur && !prev) {           // --- is still pressed ---
126                 uint16_t duration = jiffies - button_start[i];
127
128                 if (duration > 80) {
129                         // set_status_led(button, 1); // acknowledge long press
130                 }
131         } else if (cur && !prev) {            // --- just released ---
132                 uint16_t duration = jiffies - button_start[i];
133
134                 if (duration > 6 && duration < 30)
135                         short_press(button);
136                 } else if (duration > 80) {
137                         // set_status_led(button, 0);
138                         long_press(button);
139                 }
140                 // ignore other button-press durations
141         }
142 }
143