2 #include <avr/interrupt.h>
4 #include <util/delay.h>
5 #include <stdlib.h> // for NULL
9 #define WAKEUP_LIMIT 5 // times 100 ms
10 static uint16_t button_start[3];
14 unsigned char btn1 : 1;
15 unsigned char btn2 : 1;
16 unsigned char brake : 1;
18 } button_state, prev_state;
20 static unsigned char user_params[MAX_USER_PARAMS] = { 0, 0, 0 };
21 static unsigned char user_params_max[MAX_USER_PARAMS] = { 3, 2, 2 };
23 static unsigned char user_params_state = 0;
25 * Here 0 means "no setup currently in progress",
26 * 1 .. MAX_USER_PARAMS means "now short presses increase or decrease
27 * the value of user_params[user_params_state-1]"
30 static uint16_t user_params_starttime;
32 static void inline set_status_led(unsigned char n, pattern_t *pattern)
34 led_set_pattern(n + N_PWMLEDS, pattern);
37 unsigned char buttons_setup_in_progress()
39 if (user_params_state // setup in progress ...
40 // or at least one button is pressed:
47 pattern_t *buttons_setup_status0_pattern_select()
49 if (user_params_state) // Setup in progress
50 return number_pattern(user_params_state, 1);
55 pattern_t *buttons_setup_status1_pattern_select()
57 if (user_params_state) // Setup in progress
58 return number_pattern(
59 1 + user_params[user_params_state-1],
66 unsigned char get_user_param(unsigned char param)
68 if (param < MAX_USER_PARAMS)
69 return user_params[param];
70 return 0; // FIXME: internal error?
73 static inline void short_press(unsigned char button)
77 if (user_params_state == 0) {
85 param = user_params_state-1;
88 if (user_params[param])
91 user_params[param] = user_params_max[param]-1;
95 if (user_params[param] >= user_params_max[param])
96 user_params[param] = 0;
98 // FIXME: notify somebody about user_params change?
100 set_status_led(1, buttons_setup_status1_pattern_select());
102 user_params_starttime = jiffies;
105 static inline void long_press(unsigned char button)
112 // button 1 - cycle through states
115 if (user_params_state > MAX_USER_PARAMS)
116 user_params_state = 1;
118 set_status_led(0, buttons_setup_status0_pattern_select());
119 set_status_led(1, buttons_setup_status1_pattern_select());
120 user_params_starttime = jiffies;
125 DDRA &= ~_BV(PA4); // set as input
126 DDRA |= _BV(PA3); // output
127 PORTA &= ~(_BV(PA3) | _BV(PA4)); // PA4 disable internal pull-up
130 GIMSK &= ~(_BV(PCIE0) | _BV(PCIE1)); // disable pin-change IRQs
131 PCMSK0 = 0; // disable pin-change IRQs on all pins of port A
132 PCMSK1 = 0; // disable pin-change IRQs on all pins of port B
139 button_state.all = 0;
140 user_params_state = 0;
145 DDRA &= ~(_BV(PA3) | _BV(PA4)); // set as input
146 PORTA |= _BV(PA4); // enable internal pull-up
147 PORTA &= ~_BV(PA3); // disable pull-up
149 GIMSK &= ~_BV(PCIE0);
152 PCMSK0 = _BV(PCINT4);
153 // disable pin-change IRQs on all pins except PA4
154 PCMSK1 = 0; // disable pin-change IRQs on all pins of port B
157 static void handle_button(unsigned char button, unsigned char cur,
160 if (cur && !prev) { // --- just pressed ---
161 button_start[button] = jiffies;
162 set_status_led(button, NULL);
164 } else if (cur && prev) { // --- is still pressed ---
165 uint16_t duration = jiffies - button_start[button];
167 if (duration > 160) {
168 set_status_led(button, on1_pattern);
169 // acknowledge long press
171 } else if (!cur && prev) { // --- just released ---
172 uint16_t duration = jiffies - button_start[button];
174 if (duration > 6 && duration < 60) {
176 } else if (duration > 160) {
177 set_status_led(button, NULL);
180 // ignore other button-press durations
184 static void handle_brake(unsigned char cur, unsigned char prev)
186 if (cur && !prev) { // --- just pressed ---
187 button_start[2] = jiffies;
188 } else if (cur && prev) { // --- is still pressed ---
189 uint16_t duration = jiffies - button_start[2];
193 button_start[2] = jiffies - 7; // avoid overflow
195 } else if (!cur && prev) { // --- just released ---
200 void timer_check_buttons()
202 handle_button(0, button_state.btn1, prev_state.btn1);
203 handle_button(1, button_state.btn2, prev_state.btn2);
204 handle_brake(button_state.brake, prev_state.brake);
206 prev_state.all = button_state.all;
208 if (user_params_state && jiffies - user_params_starttime > 1000) {
209 user_params_state = 0;
210 set_status_led(0, buttons_setup_status0_pattern_select());
211 set_status_led(1, buttons_setup_status1_pattern_select());
215 unsigned char buttons_wait_for_release()
217 uint16_t wake_count = 0;
221 if (wake_count++ > WAKEUP_LIMIT)
222 gpio_set(0, 1); // inform the user
226 pin = PINA & _BV(PA4);
227 } while (!(pin & _BV(PA4)));
231 return wake_count > WAKEUP_LIMIT;
234 void button_adc(uint16_t adcval)
237 static unsigned char count=250;
239 PORTA &= ~_BV(PA3); // disable +5V to the hall probe
240 // adc.c will re-enable it again
242 button_state.all = 0;
243 if (adcval == 0x3FF) {
244 button_state.brake = 1;
245 } else if (adcval > 0x240) {
246 button_state.brake = 1;
247 button_state.btn2 = 1;
248 } else if (adcval > 0x180) {
250 } else if (adcval > 0xc0) {
251 button_state.btn2 = 1;
253 button_state.btn1 = 1;
268 // empty - let it wake us from sleep, but do nothing else