test.c


1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/sleep.h>
4
#include <avr/eeprom.h>
5
#include <avr/pgmspace.h>
6
#include <util/delay.h>
7
8
// CPU: ATTiny44-20PU 8MHz
9
// =======================================================================
10
11
// Ein-/Ausgänge
12
// -----------------------------------------------------------------------
13
#define ENCODER_PORT      PORTB
14
#define ENCODER_DDR        DDRB
15
#define TASTER_PIN        PINB
16
17
#define AUSGANG_PORT      PORTA
18
#define AUSGANG_DDR        DDRA
19
#define AUSGANG_PIN        PINA
20
21
#define EIN_AUS          (1 << PA7)
22
23
// Schalt-Muster
24
// -----------------------------------------------------------------------
25
#define LO            0x00                // 0000 0000
26
#define HI            0xFF                // 1111 1111
27
#define SCHALT          0x3F                // 0011 1111
28
#define AKTIV          0x80                // 1000 0000
29
30
// LED-Muster
31
// -----------------------------------------------------------------------
32
unsigned char led_setzen[4] PROGMEM    = {0b0001, 0b0010, 0b0100, 0b1000};
33
unsigned char led_loeschen[5] PROGMEM  = {0b1110, 0b1101, 0b1011, 0b0111, 0b1111};
34
35
// Tastendruck
36
// -----------------------------------------------------------------------
37
#define REPEAT_MASK         (EIN_AUS)
38
#define REPEAT_START      250
39
#define REPEAT_NEXT        100
40
#define DELAY_RESET        500
41
#define DELAY_SEQUENZ      200
42
#define DELAY_VERZOEGERUNG    400
43
44
volatile uint8_t key_state;
45
volatile uint8_t key_press;
46
volatile uint8_t key_rpt;
47
48
// =======================================================================
49
// Timer-Routine
50
// -----------------------------------------------------------------------
51
ISR (TIM0_COMPA_vect)
52
{
53
  uint8_t i;
54
  static uint8_t ct0, ct1, rpt;
55
56
  i = key_state ^ ~AUSGANG_PIN;
57
  ct0 = ~(ct0 & i);
58
  ct1 = ct0 ^ (ct1 & i);
59
  i &= ct0 & ct1;
60
  key_state ^= i;
61
  key_press |= key_state & i;
62
63
  if((key_state & REPEAT_MASK) == 0)
64
  rpt = REPEAT_START;
65
  if(--rpt == 0)
66
  {
67
    rpt = REPEAT_NEXT;
68
    key_rpt |= key_state & REPEAT_MASK;
69
  }
70
}
71
72
ISR (PCINT0_vect)
73
{
74
}
75
76
// Tastendruck auswerten
77
// -----------------------------------------------------------------------
78
uint8_t get_key_press(uint8_t key_mask)
79
{
80
  cli();
81
  key_mask &= key_press;
82
  key_press ^= key_mask;
83
  sei();
84
  return key_mask;
85
}
86
87
// Ein-/Ausänge zuweisen
88
// -----------------------------------------------------------------------
89
void init()
90
{
91
  AUSGANG_DDR = SCHALT;                      // SCHALT = Ausgang
92
                                  // RESET = Eingang (Tri-State)
93
                                  // AKTIV = Eingang
94
  AUSGANG_PORT = AKTIV;                      // AKTIV = PullUp
95
96
  ENCODER_DDR = LO;                        // ENCODER = Eingang
97
  ENCODER_PORT = HI;                        // ENCODER = PullUp
98
99
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);              // Schlafmodus definieren
100
  sleep_enable();                          // Schlafmodus aktivieren
101
  PCMSK0 = (1<<PA7);
102
103
  TCCR0A = (1<<WGM01);
104
  OCR0A = (uint8_t)(F_CPU / 64.0 * 1e-3 - 0.5);
105
  TCCR0B = (1<<CS01 | 1<<CS00);
106
  TIMSK0 = (1<<OCIE0A);
107
}
108
109
110
// Einschaltsequenz
111
// -----------------------------------------------------------------------
112
void einschalt(void)
113
{
114
  _delay_ms(DELAY_RESET);
115
  for (unsigned int a = 0; a < 4; a++)
116
  {
117
    AUSGANG_PORT |= pgm_read_word (& led_setzen[a]);
118
    _delay_ms(DELAY_SEQUENZ);
119
  }
120
  _delay_ms(DELAY_RESET);
121
  AUSGANG_PORT &= ~(pgm_read_word (& led_loeschen[4]));
122
  _delay_ms(DELAY_SEQUENZ);
123
}
124
125
// Ausschaltsequenz
126
// -----------------------------------------------------------------------
127
void ausschalt(void)
128
{
129
  AUSGANG_PORT |= pgm_read_word (& led_loeschen[4]);
130
  _delay_ms(DELAY_VERZOEGERUNG);
131
  for (unsigned int b = 3; b > 0; b--)
132
  {
133
    AUSGANG_PORT &= ~(pgm_read_word (& led_setzen[b]));
134
    _delay_ms(DELAY_SEQUENZ);
135
  }
136
  AUSGANG_PORT &= ~(pgm_read_word (& led_loeschen[4]));
137
}
138
139
// Power-down aktivieren
140
// -----------------------------------------------------------------------
141
void schlafen()
142
{
143
  TIMSK0 = 0;
144
  ausschalt();
145
  GIMSK = (1<<PCIE0);
146
  sleep_cpu();
147
  GIMSK = 0;
148
  TIMSK0 = (1<<OCIE0A);
149
}
150
151
// Hauptprogramm
152
// -----------------------------------------------------------------------
153
int main(void)
154
{
155
  uint8_t schlafen_ein = 0;
156
157
  init();                              // Startwerte setzen
158
  einschalt();
159
  sei();                              // alle Interrupt aktivieren
160
161
  for(;;)
162
  {
163
    if(get_key_press EIN_AUS)
164
    {
165
      schlafen_ein = !schlafen_ein;
166
    }
167
168
    if(schlafen_ein && !(key_state & EIN_AUS) && (AUSGANG_PIN & EIN_AUS))
169
    {
170
      schlafen();
171
    }
172
  }
173
}