1 | // ************************************************************************
|
2 | // * *
|
3 | // * Arcade Stick *
|
4 | // * Tastenprogrammierung *
|
5 | // * *
|
6 | // ************************************************************************
|
7 |
|
8 | #include <avr/io.h>
|
9 | #include <avr/eeprom.h>
|
10 | #include <avr/interrupt.h>
|
11 | #include <avr/pgmspace.h>
|
12 |
|
13 | #ifndef F_CPU
|
14 | #define F_CPU 1000000 // Processor Takt-Frequenz definieren
|
15 | #warning kein F_CPU definiert
|
16 | #endif
|
17 |
|
18 | // Tasteneingänge definieren
|
19 | // =========================
|
20 | #define KEY_DDR DDRB
|
21 | #define KEY_PORT PORTB
|
22 | #define KEY_PIN PINB
|
23 | #define KEY1 6
|
24 | #define KEY2 0
|
25 | #define KEY3 1
|
26 | #define KEY4 2
|
27 | #define KEY5 3
|
28 | #define KEY6 4
|
29 | #define KEY7 5
|
30 | #define ALL_KEYS (1<<KEY1 | 1<<KEY2 | 1<<KEY3 | 1<<KEY4 | 1<<KEY5 | 1<<KEY6 | 1<<KEY7)
|
31 |
|
32 | // Tastendrückwiederholungsdauer definieren
|
33 | // ========================================
|
34 | #define REPEAT_MASK (1<<KEY1)
|
35 | #define REPEAT_START 50 // nach 500ms
|
36 | #define REPEAT_NEXT 20 // alle 200ms
|
37 |
|
38 | // Segment und Tasten-Ausgänge definieren
|
39 | // ======================================
|
40 | #define SEGMENT_DDR DDRD
|
41 | #define SEGMENT_PORT PORTD
|
42 | #define OUT_DDR DDRC
|
43 | #define OUT_PORT PORTC
|
44 | #define OUT1 0
|
45 | #define OUT2 1
|
46 | #define OUT3 2
|
47 | #define OUT4 3
|
48 | #define OUT5 4
|
49 | #define OUT6 5
|
50 |
|
51 | #define LED0 (1 << PC0)
|
52 | #define LED1 (1 << PC1)
|
53 | #define LED2 (1 << PC2)
|
54 | #define LED3 (1 << PC3)
|
55 | #define LED4 (1 << PC4)
|
56 | #define LED5 (1 << PC5)
|
57 |
|
58 | uint8_t Pattern[NR_CONFIGS][NR_KEYS] =
|
59 | { { LED0, LED1, LED2, LED3, LED4, LED5 }, // Konfiguration 0
|
60 | { LED0, LED2, LED4, LED1, LED3, LED5 }, // Konfiguration 1
|
61 | { LED0, LED2, LED4, LED1, LED3, LED5 }, // Konfiguration 2
|
62 | { LED0, LED2, LED4, LED1, LED3, LED5 }, // Konfiguration 3
|
63 | { LED0, LED2, LED4, LED1, LED3, LED5 }, // Konfiguration 4
|
64 | { LED0, LED2, LED4, LED1, LED3, LED5 }, // Konfiguration 5
|
65 | { LED0, LED2, LED4, LED1, LED3, LED5 }, // Konfiguration 6
|
66 | { LED0, LED2, LED4, LED1, LED3, LED5 }, // Konfiguration 7
|
67 | { LED0, LED2, LED4, LED1, LED3, LED5 }, // Konfiguration 8
|
68 | };
|
69 |
|
70 | volatile uint8_t key_state; // Entprellt und invertierte Tastenstatus:
|
71 | // Bit=1 -> Taste wurde gedrückt
|
72 | volatile uint8_t key_press; // Tastendruck registriert
|
73 | volatile uint8_t key_rpt; // Tastendruckdauer
|
74 | volatile uint8_t nKeyPress; // Tastendruckanzahl
|
75 | volatile uint8_t Marker; // Speichermarkierung im 7-Segment
|
76 |
|
77 | uint8_t eeFooByte; // EEPROM Variable
|
78 |
|
79 | // Zeichentabelle für 7-Segment
|
80 | // ============================
|
81 | const unsigned char Tabelle[] PROGMEM = {249, 164, 176, 153, 146, 130, 248, 128, 144};
|
82 |
|
83 | // Timer Interrupt von 10ms definieren
|
84 | // ===================================
|
85 | ISR(TIMER0_OVF_vect)
|
86 | {
|
87 | static uint8_t ct0, ct1, rpt;
|
88 | uint8_t i;
|
89 |
|
90 | TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
|
91 |
|
92 | i = key_state ^ ~KEY_PIN; // Taste geändert?
|
93 | ct0 = ~(ct0 & i); // resete oder zähle CT0
|
94 | ct1 = ct0 ^ (ct1 & i); // resete oder zähle CT1
|
95 | i &= ct0 & ct1; // Überlauf gezählt?
|
96 | key_state ^= i; // dann Entprellstatus ändern
|
97 | key_press |= key_state & i; // 0->1: Tastendruck erkannt
|
98 |
|
99 | if((key_state & REPEAT_MASK) == 0) // Überprüfe Tastenwiederholfunktion
|
100 | rpt = REPEAT_START; // Starte Verzögerung
|
101 | if(--rpt == 0)
|
102 | {
|
103 | rpt = REPEAT_NEXT; // Wiederhole Verzögerung
|
104 | key_rpt |= key_state & REPEAT_MASK;
|
105 | }
|
106 | }
|
107 |
|
108 | // Überprüfen, ob eine Taste gedrückt wurde.
|
109 | // Jede gedrückte Taste wird nur einmal gemeldet
|
110 | // =============================================
|
111 | uint8_t get_key_press(uint8_t key_mask)
|
112 | {
|
113 | cli(); // Interrupts deaktivieren
|
114 | key_mask &= key_press; // Tasten auslesen
|
115 | key_press ^= key_mask; // Tasten löschen
|
116 | sei(); // Interrupts aktivieren
|
117 | return key_mask;
|
118 | }
|
119 |
|
120 | // Erfolgt ein längerer Tastendruck, so wird nach einiger Zeit
|
121 | // der Tastendruck automatisch wieder verworfen.
|
122 | // ===========================================================
|
123 | uint8_t get_key_rpt(uint8_t key_mask)
|
124 | {
|
125 | cli(); // Interrupts deaktivieren
|
126 | key_mask &= key_rpt; // Tasten auslesen
|
127 | key_rpt ^= key_mask; // Tasten löschen
|
128 | sei(); // Interrupts aktivieren
|
129 | return key_mask;
|
130 | }
|
131 |
|
132 | // Kurzer Tastendruck
|
133 | // ==================
|
134 | uint8_t get_key_short(uint8_t key_mask)
|
135 | {
|
136 | cli(); // Interrupts deaktivieren
|
137 | return get_key_press(~key_state & key_mask);
|
138 | }
|
139 |
|
140 | // Langer Tastendruck
|
141 | // ==================
|
142 | uint8_t get_key_long(uint8_t key_mask)
|
143 | {
|
144 | return get_key_press(get_key_rpt(key_mask));
|
145 | }
|
146 |
|
147 | int main(void)
|
148 | {
|
149 | KEY_DDR &= ~ALL_KEYS; // Tasten als Eingang definieren
|
150 | KEY_PORT |= ALL_KEYS; // PullUp aktivieren
|
151 |
|
152 | TCCR0 = (1<<CS02)|(1<<CS00); // Teilen bei 1024
|
153 | TIMSK = 1<<TOIE0; // TimerInterrupt aktivieren
|
154 |
|
155 | SEGMENT_DDR = 0xFF; // 7-Segment als Ausgang definieren
|
156 | OUT_DDR = 0xFF; // Tasten als Ausgang definieren
|
157 | OUT_PORT = 0x00; // Ausgänge auf LOW setzen
|
158 |
|
159 | nKeyPress = eeprom_read_byte(&eeFooByte); // Aktuellen Wert aus EEPROM auslesen
|
160 | SEGMENT_PORT = pgm_read_byte(&Tabelle[nKeyPress]); // und an 7-Segment übergeben
|
161 | Marker = nKeyPress; // EEPROM-Wert für Marker speichern
|
162 | sei(); // Interrupts aktivieren
|
163 |
|
164 | while(1)
|
165 | {
|
166 | if (nKeyPress == Marker)
|
167 | {
|
168 | SEGMENT_PORT = pgm_read_byte(&Tabelle[nKeyPress]) & ~(1 << 7);
|
169 | }
|
170 | if(get_key_short(1<<KEY1)) // kurzer Tastendruck
|
171 | {
|
172 | if(nKeyPress < 8) // Wurde Taste weniger als 8 mal gedrückt,
|
173 | {
|
174 | nKeyPress++; // Wert erhöhen
|
175 | }
|
176 | else
|
177 | {
|
178 | nKeyPress = 0; // ansonsten Wert zurücksetzen
|
179 | }
|
180 | SEGMENT_PORT = pgm_read_byte(&Tabelle[nKeyPress]); // Wert an 7-Segment übergeben
|
181 | }
|
182 | if(get_key_long(1<<KEY1)) // langer Tastendruck
|
183 | {
|
184 | eeprom_write_byte(&eeFooByte, nKeyPress); // Wert in EEPROM speichern
|
185 | Marker = nKeyPress; // EEPROM-Wert für Marker speichern
|
186 | }
|
187 | }
|
188 | }
|