1 | /************************************************************************/
|
2 | /* */
|
3 | /* Commodore 64 Red Edition */
|
4 | /* Encoder 4 - SD2IEC ID */
|
5 | /* */
|
6 | /************************************************************************/
|
7 | #include <avr/io.h>
|
8 | #include <avr/interrupt.h>
|
9 | #include <avr/sleep.h>
|
10 | #include <avr/eeprom.h>
|
11 | #include <avr/pgmspace.h>
|
12 | #include <util/delay.h>
|
13 |
|
14 | // CPU: ATTiny44-20PU 8MHz
|
15 | // =======================================================================
|
16 |
|
17 | // Ein-/Ausgänge
|
18 | // -----------------------------------------------------------------------
|
19 | #define ENCODER_PORT PORTB
|
20 | #define ENCODER_DDR DDRB
|
21 | #define TASTER_PIN PINB
|
22 |
|
23 | #define AUSGANG_PORT PORTA
|
24 | #define AUSGANG_DDR DDRA
|
25 | #define AUSGANG_PIN PINA
|
26 |
|
27 | #define ENCODER_A (PINB & (1 << PB0))
|
28 | #define ENCODER_B (PINB & (1 << PB1))
|
29 | #define TASTER (1 << PB2)
|
30 | #define EIN_AUS (1 << PA7)
|
31 |
|
32 | // Schalt-Muster
|
33 | // -----------------------------------------------------------------------
|
34 | #define LO 0x00 // 0000 0000
|
35 | #define HI 0xFF // 1111 1111
|
36 | #define SCHALT 0x3F // 0011 1111
|
37 | #define RESET 0x40 // 0100 0000
|
38 | #define AKTIV 0x80 // 1000 0000
|
39 |
|
40 | #define ID_LO 0x30 // 0011 0000
|
41 | #define ID_8 0x30 // 0011 0000
|
42 | #define ID_9 0x20 // 0010 0000
|
43 | #define ID_10 0x10 // 0001 0000
|
44 | #define ID_11 0x00 // 0000 0000
|
45 |
|
46 | // LED-Muster
|
47 | // -----------------------------------------------------------------------
|
48 | unsigned char led_setzen[4] PROGMEM = {0b0001, 0b0010, 0b0100, 0b1000};
|
49 | unsigned char led_loeschen[5] PROGMEM = {0b1110, 0b1101, 0b1011, 0b0111, 0b1111};
|
50 |
|
51 | // Tastendruck
|
52 | // -----------------------------------------------------------------------
|
53 | #define REPEAT_MASK (TASTER)
|
54 | #define REPEAT_MASK2 (EIN_AUS)
|
55 | #define REPEAT_START 250
|
56 | #define REPEAT_NEXT 100
|
57 | #define DELAY_RESET 500
|
58 | #define DELAY_SEQUENZ 200
|
59 | #define DELAY_VERZOEGERUNG 400
|
60 |
|
61 | volatile uint8_t key_state;
|
62 | volatile uint8_t key_press;
|
63 | volatile uint8_t key_rpt;
|
64 |
|
65 | volatile uint8_t key_state2;
|
66 | volatile uint8_t key_press2;
|
67 | volatile uint8_t key_rpt2;
|
68 |
|
69 | volatile int8_t enc_delta;
|
70 | volatile int8_t encoder = 0;
|
71 | volatile int8_t encoderwert = 0;
|
72 | volatile int16_t timeCount = 0;
|
73 | static int8_t last;
|
74 |
|
75 | // Variablen/EEPROM
|
76 | // -----------------------------------------------------------------------
|
77 | uint8_t eeprom_sdid EEMEM = 1; // 1.Byte im EEPROM für ID-Wert
|
78 | uint8_t eeprom_encoderid EEMEM = 2; // 2.Byte im EEPROM für ENCODER-Wert
|
79 | uint8_t sdid;
|
80 |
|
81 | // =======================================================================
|
82 | // Timer-Routine
|
83 | // -----------------------------------------------------------------------
|
84 | ISR (TIM0_COMPA_vect)
|
85 | {
|
86 | int8_t neu, diff;
|
87 |
|
88 | neu = 0;
|
89 | if(ENCODER_A)
|
90 | neu = 3;
|
91 | if(ENCODER_B)
|
92 | neu ^= 1;
|
93 | diff = last - neu;
|
94 | if(diff & 1)
|
95 | {
|
96 | last = neu;
|
97 | enc_delta += (diff & 2) - 1;
|
98 | }
|
99 |
|
100 | uint8_t i;
|
101 | static uint8_t ct0, ct1, rpt;
|
102 |
|
103 | i = key_state ^ ~TASTER_PIN;
|
104 | ct0 = ~(ct0 & i);
|
105 | ct1 = ct0 ^ (ct1 & i);
|
106 | i &= ct0 & ct1;
|
107 | key_state ^= i;
|
108 | key_press |= key_state & i;
|
109 |
|
110 | if((key_state & REPEAT_MASK) == 0)
|
111 | rpt = REPEAT_START;
|
112 | if(--rpt == 0)
|
113 | {
|
114 | rpt = REPEAT_NEXT;
|
115 | key_rpt |= key_state & REPEAT_MASK;
|
116 | }
|
117 |
|
118 | uint8_t h;
|
119 | static uint8_t ct2, ct3, rpt2;
|
120 |
|
121 | h = key_state2 ^ ~AUSGANG_PIN;
|
122 | ct2 = ~(ct2 & h);
|
123 | ct3 = ct2 ^ (ct3 & h);
|
124 | i &= ct2 & ct3;
|
125 | key_state2 ^= h;
|
126 | key_press2 |= key_state2 & h;
|
127 |
|
128 | if((key_state2 & REPEAT_MASK2) == 0)
|
129 | rpt2 = REPEAT_START;
|
130 | if(--rpt2 == 0)
|
131 | {
|
132 | rpt2 = REPEAT_NEXT;
|
133 | key_rpt2 |= key_state2 & REPEAT_MASK2;
|
134 | }
|
135 |
|
136 | if(timeCount > 0) timeCount--;
|
137 | }
|
138 |
|
139 | ISR (PCINT0_vect)
|
140 | {
|
141 | }
|
142 |
|
143 | // Tastendruck auswerten
|
144 | // -----------------------------------------------------------------------
|
145 | uint8_t get_key_press(uint8_t key_mask)
|
146 | {
|
147 | cli();
|
148 | key_mask &= key_press;
|
149 | key_press ^= key_mask;
|
150 | sei();
|
151 | return key_mask;
|
152 | }
|
153 |
|
154 | uint8_t get_key_press2(uint8_t key_mask2)
|
155 | {
|
156 | cli();
|
157 | key_mask2 &= key_press2;
|
158 | key_press2 ^= key_mask2;
|
159 | sei();
|
160 | return key_mask2;
|
161 | }
|
162 |
|
163 | uint8_t get_key_rpt(uint8_t key_mask)
|
164 | {
|
165 | cli();
|
166 | key_mask &= key_rpt;
|
167 | key_rpt ^= key_mask;
|
168 | sei();
|
169 | return key_mask;
|
170 | }
|
171 |
|
172 | uint8_t get_key_short(uint8_t key_mask)
|
173 | {
|
174 | cli();
|
175 | return get_key_press(~key_state & key_mask);
|
176 | }
|
177 |
|
178 | uint8_t get_key_long(uint8_t key_mask)
|
179 | {
|
180 | return get_key_press(get_key_rpt(key_mask));
|
181 | }
|
182 |
|
183 | // Encoder auswerten
|
184 | // -----------------------------------------------------------------------
|
185 | int8_t encode_read(void)
|
186 | {
|
187 | int8_t val;
|
188 |
|
189 | cli();
|
190 | val = enc_delta;
|
191 | enc_delta = val & 1;
|
192 | sei();
|
193 | return val >> 1;
|
194 | }
|
195 |
|
196 | // Prüfen ob Encoder gedreht wurde
|
197 | // -----------------------------------------------------------------------
|
198 | int8_t encode_read_timeout(void)
|
199 | {
|
200 | int8_t tmp = encode_read();
|
201 |
|
202 | if(tmp != 0) timeCount = 3000;
|
203 | return tmp;
|
204 | }
|
205 |
|
206 |
|
207 | // LED setzen
|
208 | // -----------------------------------------------------------------------
|
209 | void led_setzen_loeschen(uint8_t led_ein_aus)
|
210 | {
|
211 | AUSGANG_PORT |= pgm_read_word (& led_setzen[led_ein_aus]); // Aktiven LED-PIN setzen
|
212 | AUSGANG_PORT &= ~(pgm_read_word (& led_loeschen[led_ein_aus])); // Inaktive LED-PIN löschen
|
213 | }
|
214 |
|
215 | // SD2IEC ID-Wert setzen
|
216 | // -----------------------------------------------------------------------
|
217 | void sd_id(int8_t sdid)
|
218 | {
|
219 | AUSGANG_PORT &= ~(ID_LO); // Alle ID-PIN auf LO setzen
|
220 | AUSGANG_PORT |= (sdid); // ID-PIN setzen
|
221 | }
|
222 |
|
223 | // EPROM-Werte auslesen
|
224 | // -----------------------------------------------------------------------
|
225 | void eeprom_var(void)
|
226 | {
|
227 | if(eeprom_read_byte(&eeprom_sdid) != HI)
|
228 | {
|
229 | sdid = eeprom_read_byte(&eeprom_sdid); // KERNAL-Wert aus EEPROM auslesen
|
230 | encoder = eeprom_read_byte(&eeprom_encoderid); // ENCODER-Wert aus EEPROM auslesen
|
231 | encoderwert = encoder;
|
232 | sd_id(sdid); // gespeicherten KENRAL aktivieren
|
233 | }
|
234 | }
|
235 |
|
236 | // SD2IEC-Reset durchführen
|
237 | // -----------------------------------------------------------------------
|
238 | void reset()
|
239 | {
|
240 | AUSGANG_DDR |= (RESET); // ResetPIN = Ausgang
|
241 | AUSGANG_PORT &= ~(RESET); // ResetPIN = LO
|
242 | _delay_ms(DELAY_RESET); // Warten
|
243 | AUSGANG_DDR &= ~(RESET); // ResetPIN = Eingang
|
244 | }
|
245 |
|
246 | // Ein-/Ausänge zuweisen
|
247 | // -----------------------------------------------------------------------
|
248 | void init()
|
249 | {
|
250 | AUSGANG_DDR = SCHALT; // SCHALT = Ausgang
|
251 | // RESET = Eingang (Tri-State)
|
252 | // AKTIV = Eingang
|
253 | AUSGANG_PORT = AKTIV; // AKTIV = PullUp
|
254 |
|
255 | ENCODER_DDR = LO; // ENCODER = Eingang
|
256 | ENCODER_PORT = HI; // ENCODER = PullUp
|
257 |
|
258 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Schlafmodus definieren
|
259 | sleep_enable(); // Schlafmodus aktivieren
|
260 | }
|
261 |
|
262 | // Encoder initialisieren
|
263 | // -----------------------------------------------------------------------
|
264 | void encode_init(void)
|
265 | {
|
266 | int8_t neu;
|
267 |
|
268 | neu = 0;
|
269 | if(ENCODER_A)
|
270 | neu = 3;
|
271 | if(ENCODER_B)
|
272 | neu ^= 1;
|
273 | last = neu;
|
274 | enc_delta = 0;
|
275 |
|
276 | TCCR0A = (1<<WGM01);
|
277 | OCR0A = (uint8_t)(F_CPU / 64.0 * 1e-3 - 0.5);
|
278 | TCCR0B = (1<<CS01 | 1<<CS00);
|
279 | TIMSK0 = (1<<OCIE0A);
|
280 | }
|
281 |
|
282 | // Einschaltsequenz
|
283 | // -----------------------------------------------------------------------
|
284 | void einschalt(void)
|
285 | {
|
286 | _delay_ms(DELAY_RESET);
|
287 | for (unsigned int a = 0; a < 4; a++)
|
288 | {
|
289 | AUSGANG_PORT |= pgm_read_word (& led_setzen[a]);
|
290 | _delay_ms(DELAY_SEQUENZ);
|
291 | }
|
292 | _delay_ms(DELAY_RESET);
|
293 | AUSGANG_PORT &= ~(pgm_read_word (& led_loeschen[4]));
|
294 | _delay_ms(DELAY_SEQUENZ);
|
295 | }
|
296 |
|
297 | // Ausschaltsequenz
|
298 | // -----------------------------------------------------------------------
|
299 | void ausschalt(void)
|
300 | {
|
301 | AUSGANG_PORT |= pgm_read_word (& led_loeschen[4]);
|
302 | _delay_ms(DELAY_VERZOEGERUNG);
|
303 | for (unsigned int b = 3; b > 0; b--)
|
304 | {
|
305 | AUSGANG_PORT &= ~(pgm_read_word (& led_setzen[b]));
|
306 | _delay_ms(DELAY_SEQUENZ);
|
307 | }
|
308 | AUSGANG_PORT &= ~(pgm_read_word (& led_loeschen[4]));
|
309 | }
|
310 |
|
311 | // Power-down aktivieren
|
312 | // -----------------------------------------------------------------------
|
313 | void schlafen()
|
314 | {
|
315 | TIMSK0 = 0;
|
316 | ausschalt();
|
317 | GIMSK = 1<<INT0;
|
318 | sleep_cpu();
|
319 | GIMSK = 0;
|
320 | TIMSK0 = (1<<OCIE0A);
|
321 | }
|
322 |
|
323 | // Hauptprogramm
|
324 | // -----------------------------------------------------------------------
|
325 | int main(void)
|
326 | {
|
327 | uint8_t schlafen_ein = 0;
|
328 |
|
329 | init(); // Startwerte setzen
|
330 | eeprom_var(); // EEPROM-Werte auslesen
|
331 | einschalt(); // LED Einschaltsequenz starten
|
332 | encode_init(); // ENCODER initialisieren
|
333 | sei(); // alle Interrupt aktivieren
|
334 |
|
335 | for(;;)
|
336 | {
|
337 | ADCSRA &= !(1<<ADEN); // ADC deaktivieren
|
338 | ACSR = 0x80; // Analogcomperator deaktivieren
|
339 |
|
340 | if(get_key_press2 EIN_AUS)
|
341 | {
|
342 | schlafen_ein = !schlafen_ein;
|
343 | }
|
344 |
|
345 | if(schlafen_ein && !(key_state2 & EIN_AUS) && (AUSGANG_PIN & EIN_AUS))
|
346 | {
|
347 | schlafen();
|
348 | }
|
349 |
|
350 | encoder += encode_read_timeout(); // ENCODER-Wert auslesen
|
351 |
|
352 | if (timeCount == 0) encoder = encoderwert; // Nach Zeit zurück zum Ausgangswert
|
353 | if (encoder < 1) encoder = 0; // ENCODER-Wert darf nicht kleiner als 0
|
354 | if (encoder > 2) encoder = 3; // und größer als 3 werden
|
355 |
|
356 | switch(encoder)
|
357 | {
|
358 | case 0:
|
359 | led_setzen_loeschen(encoder);
|
360 | if (get_key_short(TASTER)) // bei kurzem Tastendruck
|
361 | {
|
362 | sd_id(ID_8);
|
363 | encoderwert = encoder;
|
364 | reset();
|
365 | }
|
366 | if(get_key_long(TASTER)) // bei langen Tastendruck
|
367 | {
|
368 | sd_id(ID_8);
|
369 | encoderwert = encoder;
|
370 | eeprom_write_byte(&eeprom_sdid, ID_8); // KERNAL-Wert in EEPROM speichern
|
371 | eeprom_write_byte(&eeprom_encoderid, encoder); // ENCODER-Wert in EEPROM speichern
|
372 | reset();
|
373 | }
|
374 | break;
|
375 |
|
376 | case 1:
|
377 | led_setzen_loeschen(encoder);
|
378 | if (get_key_short(TASTER))
|
379 | {
|
380 | sd_id(ID_9);
|
381 | encoderwert = encoder;
|
382 | reset();
|
383 | }
|
384 | if(get_key_long(TASTER))
|
385 | {
|
386 | sd_id(ID_9);
|
387 | encoderwert = encoder;
|
388 | eeprom_write_byte(&eeprom_sdid, ID_9);
|
389 | eeprom_write_byte(&eeprom_encoderid, encoder);
|
390 | reset();
|
391 | }
|
392 | break;
|
393 |
|
394 | case 2:
|
395 | led_setzen_loeschen(encoder);
|
396 | if (get_key_short(TASTER))
|
397 | {
|
398 | sd_id(ID_10);
|
399 | encoderwert = encoder;
|
400 | reset();
|
401 | }
|
402 | if(get_key_long(TASTER))
|
403 | {
|
404 | sd_id(ID_10);
|
405 | encoderwert = encoder;
|
406 | eeprom_write_byte(&eeprom_sdid, ID_10);
|
407 | eeprom_write_byte(&eeprom_encoderid, encoder);
|
408 | reset();
|
409 | }
|
410 | break;
|
411 |
|
412 | case 3:
|
413 | led_setzen_loeschen(encoder);
|
414 | if (get_key_short(TASTER))
|
415 | {
|
416 | sd_id(ID_11);
|
417 | encoderwert = encoder;
|
418 | reset();
|
419 | }
|
420 | if(get_key_long(TASTER))
|
421 | {
|
422 | sd_id(ID_11);
|
423 | encoderwert = encoder;
|
424 | eeprom_write_byte(&eeprom_sdid, ID_11);
|
425 | eeprom_write_byte(&eeprom_encoderid, encoder);
|
426 | reset();
|
427 | }
|
428 | break;
|
429 | }
|
430 | }
|
431 | }
|