forked from mrehkopf/sd2snes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimer.c
135 lines (113 loc) · 3.8 KB
/
timer.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
135
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <[email protected]>
This file was adapted from sd2iec, written by Ingo Korb.
Original copyright header follows:
*/
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
Copyright (C) 2007-2009 Ingo Korb <[email protected]>
Inspiration and low-level SD/MMC access based on code from MMC2IEC
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
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; version 2 of the License only.
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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
timer.c: System timer (and button debouncer)
*/
#include "config.h"
#include <avr/interrupt.h>
#include <avr/io.h>
#include "avrcompat.h"
#include "led.h"
#include "timer.h"
volatile tick_t ticks;
// Logical buttons
volatile uint8_t active_keys;
// Physical buttons
uint8_t buttonstate;
tick_t lastbuttonchange;
/* Called by the timer interrupt when the button state has changed */
static void buttons_changed(void) {
/* Check if the previous state was stable for two ticks */
if (time_after(ticks, lastbuttonchange+2)) {
if (active_keys & IGNORE_KEYS) {
active_keys &= ~IGNORE_KEYS;
} else if (!(buttonstate & (BUTTON_PREV|BUTTON_NEXT))) {
/* Both buttons held down */
active_keys |= KEY_HOME;
} else if (!(buttonstate & BUTTON_NEXT) &&
(BUTTON_PIN & BUTTON_NEXT)) {
/* "Next" button released */
active_keys |= KEY_NEXT;
} else if (!(buttonstate & BUTTON_PREV) &&
(BUTTON_PIN & BUTTON_NEXT)) {
active_keys |= KEY_PREV;
}
}
lastbuttonchange = ticks;
buttonstate = BUTTON_PIN & BUTTON_MASK;
}
/* The main timer interrupt */
ISR(TIMER1_COMPA_vect) {
uint8_t tmp = BUTTON_PIN & BUTTON_MASK;
if (tmp != buttonstate) {
buttons_changed();
}
ticks++;
#ifdef SINGLE_LED
if (led_state & LED_ERROR) {
if ((ticks & 15) == 0)
DIRTY_LED_PORT ^= DIRTY_LED_BIT();
} else {
if ((led_state & LED_BUSY) || (led_state & LED_DIRTY)) {
DIRTY_LED_ON();
} else {
DIRTY_LED_OFF();
}
}
#else
if (led_state & LED_ERROR)
if ((ticks & 15) == 0)
DIRTY_LED_PORT ^= DIRTY_LED_BIT();
#endif
/* Sleep button triggers when held down for 2sec */
if (time_after(ticks, lastbuttonchange+2)) {
if (!(buttonstate & BUTTON_NEXT) &&
(buttonstate & BUTTON_PREV) &&
time_after(ticks, lastbuttonchange+2*HZ) &&
!key_pressed(KEY_SLEEP)) {
/* Set ignore flag so the release doesn't trigger KEY_NEXT */
active_keys |= KEY_SLEEP | IGNORE_KEYS;
/* Avoid triggering for the next two seconds */
lastbuttonchange = ticks;
}
}
#if CONFIG_RTC_VARIANT == 1
increment_rtc();
#endif
#ifdef CONFIG_REMOTE_DISPLAY
/* Check if the display wants to be queried */
if (!(SOFTI2C_PIN & _BV(SOFTI2C_BIT_INTRQ))) {
active_keys |= KEY_DISPLAY;
}
#endif
}
void timer_init(void) {
/* Count F_CPU/8 in timer 0 */
TCCR0B = _BV(CS01);
/* Set up a 100Hz interrupt using timer 1 */
OCR1A = 1249;
TCNT1 = 0;
TCCR1A = 0;
TCCR1B = _BV(WGM12) | _BV(CS10) | _BV(CS11);
TIMSK1 |= _BV(OCIE1A);
/* Buttons */
BUTTON_DDR &= (uint8_t)~BUTTON_MASK;
BUTTON_PORT |= BUTTON_MASK;
}