-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathiob.c
134 lines (105 loc) · 3.58 KB
/
iob.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
* Edited by Oliver Martin for LaFortuna 05/05/2018
*
* ( Using some code from previous tasks: ruota.c )
* ( See license for this code below )
*/
/* ruota.c
Copyright Peter Dannegger (danni@specs.de)
http://www.mikrocontroller.net/articles/Entprellung
http://www.mikrocontroller.net/articles/Drehgeber
Slightly adapted by Klaus-Peter Zauner for FortunaOS, March 2015
*/
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "iob.h"
#define ARROW_KEYS (_BV(PC2) | _BV(PC3) | _BV(PC4) | _BV(PC5))
#define COMPASS_SWITCHES (_BV(SWW)|_BV(SWS)|_BV(SWE)|_BV(SWN))
#define ALL_SWITCHES (_BV(SWC) | COMPASS_SWITCHES | _BV(OS_CD))
volatile uint8_t iob_state;
volatile int16_t iob_delta;
volatile uint8_t switch_state; /* debounced and inverted key state:
bit = 1: key pressed */
volatile uint8_t switch_press; /* key press detect */
volatile uint8_t switch_rpt; /* key long press and repeat */
void iob_init()
{
iob_state = 0;
// Disable JTAG
MCUCR |= _BV(JTD);
MCUCR |= _BV(JTD);
DDRC &= ~COMPASS_SWITCHES; /* configure compass buttons for input */
PORTC |= COMPASS_SWITCHES; /* and turn on pull up resistors */
}
void scan_switches() {
static uint8_t ct0, ct1, rpt;
uint8_t i;
cli();
/*
Overlay port E for central button of switch wheel and Port B
for SD card detection switch:
*/
i = switch_state ^ ~( (PINC|_BV(SWC)|_BV(OS_CD)) \
& (PINE|~_BV(SWC)) \
& (PINB|~_BV(OS_CD))); /* switch has changed */
ct0 = ~( ct0 & i ); /* reset or count ct0 */
ct1 = ct0 ^ (ct1 & i); /* reset or count ct1 */
i &= ct0 & ct1; /* count until roll over ? */
switch_state ^= i; /* then toggle debounced state */
switch_press |= switch_state & i; /* 0->1: key press detect */
if( (switch_state & ALL_SWITCHES) == 0 ) /* check repeat function */
rpt = REPEAT_START; /* start delay */
if( --rpt == 0 ){
rpt = REPEAT_NEXT; /* repeat delay */
switch_rpt |= switch_state & ALL_SWITCHES;
}
sei();
}
/*
Check if a key has been pressed
Each pressed key is reported only once.
*/
uint8_t get_switch_press( uint8_t switch_mask ) {
cli(); /* read and clear atomic! */
switch_mask &= switch_press; /* read key(s) */
switch_press ^= switch_mask; /* clear key(s) */
sei();
return switch_mask;
}
/*
Check if a key has been pressed long enough such that the
key repeat functionality kicks in. After a small setup delay
the key is reported being pressed in subsequent calls
to this function. This simulates the user repeatedly
pressing and releasing the key.
*/
uint8_t get_switch_rpt( uint8_t switch_mask ) {
cli(); /* read and clear atomic! */
switch_mask &= switch_rpt; /* read key(s) */
switch_rpt ^= switch_mask; /* clear key(s) */
sei();
return switch_mask;
}
/*
Check if a key is pressed right now
*/
uint8_t get_switch_state( uint8_t switch_mask ) {
switch_mask &= switch_state;
return switch_mask;
}
/*
Read key state and key press atomic!
*/
uint8_t get_switch_short( uint8_t switch_mask ) {
cli();
return get_switch_press( ~switch_state & switch_mask );
}
/*
Key pressed and held long enough that a repeat would
trigger if enabled.
*/
uint8_t get_switch_long( uint8_t switch_mask ) {
return get_switch_press( get_switch_rpt( switch_mask ));
}