-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathbuttons.c
120 lines (91 loc) · 2.95 KB
/
buttons.c
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
/* Interrupt routine for tick count and handling the buttons */
#include "buttons.h"
#include "BIOS.h"
#include <stm32f10x.h>
// Milliseconds since boot, good for two months of operation.
// Also, most functions will handle overflows properly.
static volatile uint32_t TICKCOUNT = 0;
// Timestamp when was the last time some key was down
static volatile uint32_t KEYS_LAST_DOWN = 0;
// Timestamp when was the last time all keys were up
static volatile uint32_t KEYS_LAST_UP = 0;
// Flags for keys that have been pressed since the last time they were read
static volatile uint32_t KEYS_PRESSED = 0;
// Flags for keys that are currently down
static volatile uint32_t KEYS_DOWN = 0;
// Timestamp when was the last time KEYS_DOWN changed
static volatile uint32_t KEYS_LAST_CHANGED = 0;
// Debounce time for keys, in milliseconds
#define DEBOUNCE 10
// Repeat time for scroller keys
#define REPEAT_DELAY 300
#define REPEAT_PERIOD 100
#define REPEAT_KEYS (SCROLL1_LEFT | SCROLL1_RIGHT | SCROLL2_LEFT | SCROLL2_RIGHT)
void __irq__ TIM3_IRQHandler(void)
{
TIM3->SR = 0; // Clear interrupt flag
TICKCOUNT++;
uint32_t keys = (~__Get(KEY_STATUS)) & ALL_KEYS;
// Only record keypresses the first time the key goes down
if (keys && TICKCOUNT - KEYS_LAST_DOWN > DEBOUNCE)
KEYS_PRESSED |= keys;
if (keys) KEYS_LAST_DOWN = TICKCOUNT;
if (!keys) KEYS_LAST_UP = TICKCOUNT;
if (keys != KEYS_DOWN)
{
KEYS_DOWN = keys;
KEYS_LAST_CHANGED = TICKCOUNT;
}
uint32_t time_down = TICKCOUNT - KEYS_LAST_CHANGED;
if (time_down > REPEAT_DELAY && (keys & REPEAT_KEYS))
{
if ((time_down - REPEAT_DELAY) % REPEAT_PERIOD == 0)
KEYS_PRESSED |= (keys & REPEAT_KEYS);
}
TimerTick();
}
// Check if some keys have been pressed, but don't clear the key status.
uint32_t peek_keys(uint32_t mask)
{
return KEYS_PRESSED & mask;
}
// Check if some keys have been pressed, and clear the status for them.
uint32_t get_keys(uint32_t mask)
{
return __sync_fetch_and_and(&KEYS_PRESSED, ~mask) & mask;
}
// Check if some keys are being held down
// Returns the keys that are still down and the number of milliseconds they've
// been down.
uint32_t held_keys(uint32_t mask, uint32_t *ticks)
{
uint32_t keys, time;
do
{
time = KEYS_LAST_CHANGED;
keys = KEYS_DOWN & mask;
} while (time != KEYS_LAST_CHANGED);
*ticks = TICKCOUNT - time;
return keys;
}
// Get number of milliseconds passed since boot
uint32_t get_time()
{
return TICKCOUNT;
}
void delay_ms(uint32_t milliseconds)
{
uint32_t start = TICKCOUNT;
while (TICKCOUNT - start < milliseconds);
}
#include <fix16.h>
int scroller_speed()
{
uint32_t time = TICKCOUNT - KEYS_LAST_UP;
if (time < 500)
return 1;
if (time > 10000)
time = 10000;
fix16_t a = fix16_div(fix16_from_int(time), fix16_from_int(2171));
return 1 + fix16_to_int(fix16_exp(a));
}