encoder4.c


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
}