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;
17 unsigned char brake_working : 1;
18 unsigned char brake_reported : 1;
20 } button_state, prev_state;
22 static unsigned char user_params[MAX_USER_PARAMS] = { 0, 0, 0 };
23 static unsigned char user_params_max[MAX_USER_PARAMS] = { 3, 2, 2 };
25 static unsigned char user_params_state = 0;
27 * Here 0 means "no setup currently in progress",
28 * 1 .. MAX_USER_PARAMS means "now short presses increase or decrease
29 * the value of user_params[user_params_state-1]"
32 static uint16_t user_params_starttime;
34 static void inline set_status_led(unsigned char n, pattern_t *pattern)
36 led_set_pattern(n + N_PWMLEDS, pattern);
39 unsigned char buttons_setup_in_progress()
41 if (user_params_state // setup in progress ...
42 // or at least one button is pressed:
49 pattern_t *buttons_setup_status0_pattern_select()
51 if (user_params_state) // Setup in progress
52 return number_pattern(user_params_state, 1);
57 pattern_t *buttons_setup_status1_pattern_select()
59 if (user_params_state) // Setup in progress
60 return number_pattern(
61 1 + user_params[user_params_state-1],
68 unsigned char get_user_param(unsigned char param)
70 if (param < MAX_USER_PARAMS)
71 return user_params[param];
72 return 0; // FIXME: internal error?
75 static inline void short_press(unsigned char button)
79 if (user_params_state == 0) {
87 param = user_params_state-1;
90 if (user_params[param])
93 user_params[param] = user_params_max[param]-1;
97 if (user_params[param] >= user_params_max[param])
98 user_params[param] = 0;
100 // FIXME: notify somebody about user_params change?
102 set_status_led(1, buttons_setup_status1_pattern_select());
104 user_params_starttime = jiffies;
107 static inline void long_press(unsigned char button)
114 // button 1 - cycle through states
117 if (user_params_state > MAX_USER_PARAMS)
118 user_params_state = 1;
120 set_status_led(0, buttons_setup_status0_pattern_select());
121 set_status_led(1, buttons_setup_status1_pattern_select());
122 user_params_starttime = jiffies;
127 DDRA &= ~_BV(PA4); // set as input
128 DDRA |= _BV(PA3); // output
129 PORTA &= ~(_BV(PA3) | _BV(PA4)); // PA4 disable internal pull-up
132 GIMSK &= ~(_BV(PCIE0) | _BV(PCIE1)); // disable pin-change IRQs
133 PCMSK0 = 0; // disable pin-change IRQs on all pins of port A
134 PCMSK1 = 0; // disable pin-change IRQs on all pins of port B
141 button_state.all = 0;
142 user_params_state = 0;
147 DDRA &= ~(_BV(PA3) | _BV(PA4)); // set as input
148 PORTA |= _BV(PA4); // enable internal pull-up
149 PORTA &= ~_BV(PA3); // disable pull-up
151 GIMSK &= ~_BV(PCIE0);
154 PCMSK0 = _BV(PCINT4);
155 // disable pin-change IRQs on all pins except PA4
156 PCMSK1 = 0; // disable pin-change IRQs on all pins of port B
159 static void handle_button(unsigned char button, unsigned char cur,
162 if (cur && !prev) { // --- just pressed ---
163 button_start[button] = jiffies;
164 set_status_led(button, NULL);
166 } else if (cur && prev) { // --- is still pressed ---
167 uint16_t duration = jiffies - button_start[button];
169 if (duration > 160) {
170 set_status_led(button, on1_pattern);
171 // acknowledge long press
173 } else if (!cur && prev) { // --- just released ---
174 uint16_t duration = jiffies - button_start[button];
176 if (duration > 6 && duration < 60) {
178 } else if (duration > 160) {
179 set_status_led(button, NULL);
182 // ignore other button-press durations
186 static void handle_brake(unsigned char cur, unsigned char prev)
188 if (cur && !prev) { // --- just pressed ---
189 button_start[2] = jiffies;
190 } else if (!cur && prev) { // --- just released ---
191 button_start[2] = jiffies;
192 } else { // --- no change ---
193 uint16_t duration = jiffies - button_start[2];
197 if (button_state.brake_working
198 && !button_state.brake_reported) {
199 button_state.brake_reported = 1;
203 button_state.brake_working = 1;
204 if (button_state.brake_reported) {
205 button_state.brake_reported = 0;
209 button_start[2] = jiffies - 7; // avoid overflow
214 void timer_check_buttons()
216 handle_button(0, button_state.btn1, prev_state.btn1);
218 // when button 1 is on, all other states are unreadable
219 if (button_state.btn1) {
220 prev_state.btn1 = button_state.btn1;
222 handle_button(1, button_state.btn2, prev_state.btn2);
223 handle_brake(button_state.brake, prev_state.brake);
224 prev_state.all = button_state.all;
227 if (user_params_state && jiffies - user_params_starttime > 1000) {
228 user_params_state = 0;
229 set_status_led(0, buttons_setup_status0_pattern_select());
230 set_status_led(1, buttons_setup_status1_pattern_select());
234 unsigned char buttons_wait_for_release()
236 uint16_t wake_count = 0;
240 if (wake_count++ > WAKEUP_LIMIT)
241 gpio_set(0, 1); // inform the user
245 pin = PINA & _BV(PA4);
246 } while (!(pin & _BV(PA4)));
250 return wake_count > WAKEUP_LIMIT;
253 void button_adc(uint16_t adcval)
256 static unsigned char count=250;
258 PORTA &= ~_BV(PA3); // disable +5V to the hall probe
259 // adc.c will re-enable it again
261 button_state.btn1 = 0;
262 button_state.btn2 = 0;
263 button_state.brake = 0;
265 if (adcval == 0x3FF) {
266 button_state.brake = 1;
267 } else if (adcval > 0x240) {
268 button_state.brake = 1;
269 button_state.btn2 = 1;
270 } else if (adcval > 0x180) {
272 } else if (adcval > 0xc0) {
273 button_state.btn2 = 1;
275 button_state.btn1 = 1;
290 // empty - let it wake us from sleep, but do nothing else