1 | /************************************************************************/
|
2 | /* */
|
3 | /* Commodore 1541-II Bubble */
|
4 | /* Toolbox */
|
5 | /* */
|
6 | /************************************************************************/
|
7 | #include <avr/io.h>
|
8 | #include <avr/interrupt.h>
|
9 | #include <avr/eeprom.h>
|
10 | #include <util/delay.h>
|
11 |
|
12 | // CPU: ATtiny2313-20PU 8MHz
|
13 | // =======================================================================
|
14 |
|
15 | #define LEDS_PORT PORTB // 7-Segment PORT
|
16 | #define TASTER_PORT PORTA // Taster PORT
|
17 | #define SCHALTER_PORT PORTD // Schalter PORT
|
18 |
|
19 | #define LEDS_DDR DDRB
|
20 | #define TASTER_DDR DDRA
|
21 | #define SCHALTER_DDR DDRD
|
22 |
|
23 | #define TASTER_PIN PINA
|
24 |
|
25 | #define MENU_TASTER (1 << PA0)
|
26 | #define LICHT_EIN (PINA & 1 << PA1)
|
27 |
|
28 |
|
29 | // Schaltmuster
|
30 | // -----------------------------------------------------------------------
|
31 | #define EINSCHALT 0x70 // 0111 0000
|
32 | #define ALL_LOW 0x00 // 0000 0000
|
33 | #define ALL_HI 0xFF // 1111 1111
|
34 | #define RESET 0x40 // 0100 0000
|
35 | #define ID_HI 0x30 // 0011 0000
|
36 | #define ID_8 0x30 // 0011 0000
|
37 | #define ID_9 0x20 // 0010 0000
|
38 | #define ID_10 0x10 // 0001 0000
|
39 | #define ID_11 0x00 // 0000 0000
|
40 | #define WRITE 0x08 // 0000 1000
|
41 |
|
42 | // Tastendruck
|
43 | // -----------------------------------------------------------------------
|
44 | #define REPEAT_START 50 // nach 500ms
|
45 | #define REPEAT_NEXT 20 // alle 200ms
|
46 |
|
47 | #define DELAY 50
|
48 |
|
49 | // Segment Anzeige
|
50 | // -----------------------------------------------------------------------
|
51 | #define _8 0x7F // 0111 1111
|
52 | #define _9 0x67 // 0110 0111
|
53 | #define _10 0x3F // 0011 1111
|
54 | #define _11 0x36 // 0000 0110
|
55 | #define _I 0x30 // 0011 0000
|
56 | #define _D 0x5E // 0101 1110
|
57 | #define _S 0x6D // 0110 1101
|
58 | #define _R 0x50 // 0101 0000
|
59 | #define _A 0x77 // 0111 0111
|
60 | #define _C 0x39 // 0011 1001
|
61 | #define _J 0x1E // 0000 1110
|
62 | #define _E 0x79 // 0111 1001
|
63 | #define _H 0x80 // 1000 0000
|
64 |
|
65 | volatile int8_t nSelect = 0;
|
66 | volatile int8_t ende;
|
67 | volatile uint8_t marker;
|
68 |
|
69 | static int8_t lichtval;
|
70 | static int16_t timeCount = 0;
|
71 | static int16_t lichtCount = 0;
|
72 |
|
73 | uint8_t key_state; // Entprellt und invertierter Tastenstatus:
|
74 | // bit = 1: Taste gedrückt
|
75 | uint8_t key_press; // Tastendruck erkannt
|
76 | uint8_t key_rpt; // Langer Tastendruck mit Wiederholung
|
77 | uint8_t eeprom_floppyid EEMEM = 1; // Speicherstelle 1 im EEPROM für Floppy-ID
|
78 | uint8_t licht = 1;
|
79 | uint8_t laufwerkid;
|
80 | uint8_t laufwerkidled;
|
81 |
|
82 | ISR(TIMER0_OVF_vect)
|
83 | {
|
84 | static uint8_t ct0, ct1, rpt;
|
85 | uint8_t i;
|
86 |
|
87 | TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
|
88 |
|
89 | i = key_state ^ ~TASTER_PIN; // Taste gewechselt ?
|
90 | ct0 = ~(ct0 & i); // Reset oder zähle ct0
|
91 | ct1 = ct0 ^ (ct1 & i); // Reset oder zähle ct1
|
92 | i &= ct0 & ct1; // count until roll over ?
|
93 | key_state ^= i; // then toggle debounced state
|
94 | key_press |= key_state & i; // 0 -> 1: Tastendruck registrieren
|
95 |
|
96 | if((key_state & MENU_TASTER) == 0) // Überprüfe Wiederholfunktion
|
97 | rpt = REPEAT_START; // Verzögerung starten
|
98 | if(--rpt == 0)
|
99 | {
|
100 | rpt = REPEAT_NEXT; // Wiederhole Verzögerung
|
101 | key_rpt |= key_state & MENU_TASTER;
|
102 | }
|
103 |
|
104 | if(timeCount > 0) // Timer für Menüwechsel
|
105 | {
|
106 | timeCount--;
|
107 | if(timeCount == 0)
|
108 | {
|
109 | nSelect = 0;
|
110 | ende = 1;
|
111 | }
|
112 | }
|
113 |
|
114 | if(lichtCount > 0) // Timer für Diskwechselimpuls
|
115 | {
|
116 | SCHALTER_PORT |= (WRITE);
|
117 | lichtCount--;
|
118 | if(lichtCount == 0)
|
119 | lichtval = LICHT_EIN;
|
120 | }
|
121 |
|
122 | if(licht == 0) // Schreibschutzerkennung = AUS
|
123 | {
|
124 | if(LICHT_EIN) // wenn schreibgeschützt (HIGH)
|
125 | {
|
126 | SCHALTER_PORT &= ~(WRITE); // LICHTAUSGANG = LOW / Schreiben erlaubt
|
127 | marker &= ~(_H); // 7-Segment Punkt löschen
|
128 | }
|
129 | if(!(LICHT_EIN)) // wenn nicht schreibgeschützt (LOW)
|
130 | licht = 1;
|
131 | }
|
132 |
|
133 | if(licht == 1) // Schreibschutzerkennung = EIN
|
134 | {
|
135 | if(LICHT_EIN) // wenn schreibgeschützt (HIGH)
|
136 | {
|
137 | SCHALTER_PORT |= (WRITE); // LICHTAUSGANG = HIGH / Schreiben nicht erlaubt
|
138 | marker |= (_H); // 7-Segment Punkt anzeigen
|
139 | }
|
140 | if(!(LICHT_EIN)) // wenn nicht schreibgeschützt (LOW)
|
141 | {
|
142 | SCHALTER_PORT &= ~(WRITE); // LICHTAUSGANG = LOW / Schreiben erlaubt
|
143 | marker &= ~(_H); // 7-Segment Punkt löschen
|
144 | }
|
145 | }
|
146 |
|
147 | if(licht == 2) // Schreibschutzerkennung = IMMER AUS
|
148 | {
|
149 | if((LICHT_EIN != lichtval) && (lichtCount == 0)) // wenn schreibgeschützt (HIGH) und Diskwechsel erfolgt
|
150 | lichtCount = 25; // LICHTAUSGANG für 150ms auf HIGH
|
151 |
|
152 | if(LICHT_EIN == lichtval)
|
153 | SCHALTER_PORT &= ~(WRITE); // LICHTAUSGANG = LOW / Schreiben nicht erlaubt
|
154 |
|
155 | }
|
156 | }
|
157 |
|
158 | uint8_t get_key_press(uint8_t key_mask)
|
159 | {
|
160 | cli(); // Lese und lösche Atomic
|
161 | key_mask &= key_press; // Tastenzustand lesen
|
162 | key_press ^= key_mask; // Tastenzustand löschen
|
163 | sei();
|
164 | return key_mask;
|
165 | }
|
166 |
|
167 | uint8_t get_key_rpt(uint8_t key_mask)
|
168 | {
|
169 | cli(); // Lese und lösche Atomic
|
170 | key_mask &= key_rpt; // Tastenzustand lesen
|
171 | key_rpt ^= key_mask; // Tastenzustand löschen
|
172 | sei();
|
173 | return key_mask;
|
174 | }
|
175 |
|
176 | uint8_t get_key_short(uint8_t key_mask)
|
177 | {
|
178 | cli(); // Tastenzustand lesen und Tastendruck Atomic
|
179 | return get_key_press(~key_state & key_mask);
|
180 | }
|
181 |
|
182 | uint8_t get_key_long(uint8_t key_mask)
|
183 | {
|
184 | return get_key_press(get_key_rpt(key_mask));
|
185 | }
|
186 |
|
187 | void blinken(uint8_t taste)
|
188 | {
|
189 | static uint16_t zaehler=0;
|
190 |
|
191 | if (taste)
|
192 | {
|
193 | if (zaehler>=999)
|
194 | {
|
195 | marker ^= (_H);
|
196 | zaehler=0;
|
197 | }
|
198 | }
|
199 | else
|
200 | {
|
201 | if (zaehler>=99)
|
202 | {
|
203 | marker ^= (_H);
|
204 | zaehler=0;
|
205 | }
|
206 | }
|
207 | _delay_ms(1);
|
208 | zaehler++;
|
209 | }
|
210 |
|
211 | void floppy_id(int8_t floppyid)
|
212 | {
|
213 | SCHALTER_PORT |= (ID_HI); // Alle ID-PIN = HIGH
|
214 | SCHALTER_PORT &= ~(floppyid); // ID-PIN = LOW
|
215 |
|
216 | switch(floppyid)
|
217 | {
|
218 | case ID_8:
|
219 | laufwerkidled = _8;
|
220 | break;
|
221 | case ID_9:
|
222 | laufwerkidled = _9;
|
223 | break;
|
224 | case ID_10:
|
225 | laufwerkidled = _10;
|
226 | break;
|
227 | case ID_11:
|
228 | laufwerkidled = _11;
|
229 | break;
|
230 | }
|
231 | }
|
232 |
|
233 | void reset()
|
234 | {
|
235 | SCHALTER_DDR |= (RESET); // ResetPIN = Ausgang
|
236 | SCHALTER_PORT &= ~(RESET); // ResetPIN = LOW
|
237 | _delay_ms(DELAY); // Warten
|
238 | SCHALTER_DDR &= ~(RESET); // ResetPIN = Eingang
|
239 | SCHALTER_PORT |= (RESET); // ResetPIN = PullUp
|
240 | }
|
241 |
|
242 | void eeprom_var(void)
|
243 | {
|
244 | if(eeprom_read_byte(&eeprom_floppyid) != ALL_HI)
|
245 | {
|
246 | laufwerkid = eeprom_read_byte(&eeprom_floppyid); // Floppy-ID aus EEPROM auslesen
|
247 | floppy_id(laufwerkid);
|
248 | }
|
249 | }
|
250 |
|
251 | void ioinit()
|
252 | {
|
253 | LEDS_DDR = ALL_HI; // 7-SEGMENT-PORT = Ausgang
|
254 |
|
255 | SCHALTER_DDR = ALL_HI; // SCHALT-PORT = Ausgang
|
256 | SCHALTER_PORT = EINSCHALT; // EINSCHALT-ZUSTAND
|
257 |
|
258 | TASTER_DDR = ALL_LOW; // LICHTSCHRANKE = Eingang
|
259 | TASTER_PORT = ALL_HI; // LICHTSCHRANKE = PullUp
|
260 |
|
261 | TCCR0B = (1 << CS02) | (1 << CS00); // Interrupt durch 1024 teilen
|
262 | TIMSK = 1 << TOIE0; // Timer Interrupt aktivieren
|
263 | }
|
264 |
|
265 | int main(void)
|
266 | {
|
267 | int32_t val = 0;
|
268 | ioinit();
|
269 | reset();
|
270 | eeprom_var();
|
271 |
|
272 | sei(); // Interrupts aktivieren
|
273 |
|
274 | for(;;)
|
275 | {
|
276 | LEDS_PORT = laufwerkidled | marker;
|
277 |
|
278 | if(get_key_short(MENU_TASTER))
|
279 | {
|
280 | timeCount = 300; // Zeitzähler auf 5sek setzen
|
281 | val = 0; // Tasterwert zurücksetzen
|
282 | }
|
283 |
|
284 | while(timeCount > 0)
|
285 | {
|
286 | if(get_key_short(MENU_TASTER))
|
287 | {
|
288 | timeCount = 300;
|
289 | val++; // Tasterwert um 1 erhöhen
|
290 | }
|
291 |
|
292 | if(nSelect == 0) // Haupt-Menü
|
293 | {
|
294 | if (val > 2) val = 0;
|
295 | }
|
296 |
|
297 | if(nSelect == 1) // Floppy-ID Menü
|
298 | {
|
299 | if (val > 6) val = 3;
|
300 | }
|
301 |
|
302 | if(nSelect == 2) // Schreibschutz-Menü
|
303 | {
|
304 | if (val > 9) val = 7;
|
305 | }
|
306 |
|
307 | switch(val)
|
308 | {
|
309 | // Hauptmenü
|
310 | case 0:
|
311 | LEDS_PORT = _I; // I -> ID
|
312 | if(get_key_long(MENU_TASTER))
|
313 | {
|
314 | val = 3;
|
315 | nSelect = 1;
|
316 | }
|
317 | break;
|
318 | case 1:
|
319 | LEDS_PORT = _S; // S -> Schreibschutz
|
320 | if(get_key_long(MENU_TASTER))
|
321 | {
|
322 | val = 7;
|
323 | nSelect = 2;
|
324 | }
|
325 | break;
|
326 | case 2:
|
327 | LEDS_PORT = _R; // R -> Reset
|
328 | if(get_key_long(MENU_TASTER))
|
329 | {
|
330 | reset();
|
331 | val = 0;
|
332 | nSelect = 0;
|
333 | timeCount = 1;
|
334 | }
|
335 | break;
|
336 |
|
337 | // Floppy-ID
|
338 | case 3:
|
339 | LEDS_PORT = _8; // 8 -> ID 8
|
340 |
|
341 | if(get_key_long(MENU_TASTER))
|
342 | {
|
343 | floppy_id(ID_8);
|
344 | eeprom_write_byte(&eeprom_floppyid, ID_8);
|
345 | reset();
|
346 | timeCount = 1;
|
347 | }
|
348 | break;
|
349 | case 4:
|
350 | LEDS_PORT = _9; // 9 -> ID 9
|
351 |
|
352 | if(get_key_long(MENU_TASTER))
|
353 | {
|
354 | floppy_id(ID_9);
|
355 | eeprom_write_byte(&eeprom_floppyid, ID_9);
|
356 | reset();
|
357 | timeCount = 1;
|
358 | }
|
359 | break;
|
360 | case 5:
|
361 | LEDS_PORT = _10; // 10 -> ID 10
|
362 |
|
363 | if(get_key_long(MENU_TASTER))
|
364 | {
|
365 | floppy_id(ID_10);
|
366 | eeprom_write_byte(&eeprom_floppyid, ID_10);
|
367 | reset();
|
368 | timeCount = 1;
|
369 | }
|
370 | break;
|
371 | case 6:
|
372 | LEDS_PORT = _11; // 11 -> ID 11
|
373 |
|
374 | if(get_key_long(MENU_TASTER))
|
375 | {
|
376 | floppy_id(ID_11);
|
377 | eeprom_write_byte(&eeprom_floppyid, ID_11);
|
378 | reset();
|
379 | timeCount = 1;
|
380 | }
|
381 | break;
|
382 |
|
383 | // Schreibschutzerkennung
|
384 | case 7:
|
385 | LEDS_PORT = _A; // A -> Aus
|
386 | if(get_key_long(MENU_TASTER))
|
387 | {
|
388 | licht = 0;
|
389 | timeCount = 1;
|
390 | }
|
391 | break;
|
392 | case 8:
|
393 | LEDS_PORT = _E; // E -> Ein
|
394 | if(get_key_long(MENU_TASTER))
|
395 | {
|
396 | licht = 1;
|
397 | timeCount = 1;
|
398 | }
|
399 | break;
|
400 | case 9:
|
401 | LEDS_PORT = _I; // I -> Immer
|
402 | if(get_key_long(MENU_TASTER))
|
403 | {
|
404 | lichtval = LICHT_EIN;
|
405 | licht = 2;
|
406 | blinken(LICHT_EIN);
|
407 | timeCount = 1;
|
408 | }
|
409 | break;
|
410 | }
|
411 | }
|
412 | }
|
413 | }
|