/
button.ino
138 lines (123 loc) · 3.64 KB
/
button.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Iambino - Iambic Keyer for Arduino
// Copyright (C) 2013 David Turnbull AE9RB
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BUTTON_DEBOUNCE_DN 2000 // 2ms
#define BUTTON_DEBOUNCE_UP 50000 // 50ms
#define BUTTON_REPEAT_DELAY 400000
#define BUTTON_REPEAT_EACH 150000
#define BUTTON_ADC_RIGHT 0
#define BUTTON_ADC_UP 145
#define BUTTON_ADC_DOWN 329
#define BUTTON_ADC_LEFT 505
#define BUTTON_ADC_SELECT 741
#define BUTTON_ADC_WINDOW 10
bool button_repeat_fast;
void button_fast(bool is_fast) {
button_repeat_fast = is_fast;
}
uint8_t button_read(long mark) {
static uint8_t state = 0, eat, pressed;
static long debounce, repeat;
uint8_t button = BUTTON_NONE;
int adc;
adc = analogRead( BUTTON_APIN );
if( adc < ( BUTTON_ADC_RIGHT + BUTTON_ADC_WINDOW ) )
{
button = BUTTON_SELECT;
}
else if( adc >= ( BUTTON_ADC_UP - BUTTON_ADC_WINDOW )
&& adc <= ( BUTTON_ADC_UP + BUTTON_ADC_WINDOW ) )
{
button = BUTTON_RIGHT;
}
else if( adc >= ( BUTTON_ADC_DOWN - BUTTON_ADC_WINDOW )
&& adc <= ( BUTTON_ADC_DOWN + BUTTON_ADC_WINDOW ) )
{
button = BUTTON_UP;
}
else if( adc >= ( BUTTON_ADC_LEFT - BUTTON_ADC_WINDOW )
&& adc <= ( BUTTON_ADC_LEFT + BUTTON_ADC_WINDOW ) )
{
button = BUTTON_DOWN;
}
else if( adc >= ( BUTTON_ADC_SELECT - BUTTON_ADC_WINDOW )
&& adc <= ( BUTTON_ADC_SELECT + BUTTON_ADC_WINDOW ) )
{
button = BUTTON_LEFT;
}
switch(state) {
case 0:
if (button) {
debounce = mark + BUTTON_DEBOUNCE_DN;
state = 1;
eat = 1;
}
break;
case 1:
if (mark - debounce >= 0) {
if (button) {
state = 2;
repeat = mark + BUTTON_REPEAT_DELAY;
pressed = button;
return button;
}
state = 0;
}
break;
case 2:
if (button) debounce = mark + BUTTON_DEBOUNCE_UP;
else if (mark - debounce >= 0) {
state = 0;
return pressed | BUTTON_RELEASE;
}
if (mark - repeat >= 0) {
repeat = mark + BUTTON_REPEAT_EACH;
eat ^= 1;
if (!eat || ((button & BUTTON_UP || button & BUTTON_DOWN) && button_repeat_fast))
return pressed | BUTTON_REPEAT;
}
break;
}
return BUTTON_NONE;
}
// TODO start at 512 and save these in EEPROM
// prototype hardware is full range so this is ok for now
int button_pot_min = 0;
int button_pot_max = 1023;
bool button_pot() {
static unsigned int prev_speed;
unsigned int seg, pos, mod, speed, dz;
int i = analogRead(POT_APIN);
if (i > button_pot_max) {
button_pot_max = i;
cfg_set_speed(0);
}
if (i < button_pot_min) {
button_pot_min = i;
cfg_set_speed(0);
}
seg = (1 + button_pot_max - button_pot_min) / (1 + cfg.speed_max - cfg.speed_min);
dz = seg / 4;
pos = i - button_pot_min;
mod = pos % seg;
speed = pos / seg + cfg.speed_min;
if (speed > cfg.speed_max) speed = cfg.speed_max;
if (cfg_get_speed()==0 || (mod > dz && seg-mod > dz && prev_speed != speed)) {
cfg_set_speed(speed);
prev_speed = speed;
return true;
}
return false;
}