1 | // ----------------------------------------------------------------------------
|
2 | // INCLUDES
|
3 | // ----------------------------------------------------------------------------
|
4 |
|
5 | #include <stdint.h>
|
6 | #include <avr/io.h>
|
7 | #include <avr/interrupt.h>
|
8 | #include <inttypes.h>
|
9 | #include <avr/wdt.h>
|
10 | #include <util/delay.h>
|
11 |
|
12 |
|
13 | // ----------------------------------------------------------------------------
|
14 | // DEFINES
|
15 | // ----------------------------------------------------------------------------
|
16 | #ifndef F_CPU
|
17 | #define F_CPU 8000000UL // processor clock frequency 8Mhz
|
18 | #endif
|
19 |
|
20 | #define REPEAT_START 41
|
21 | #define REPEAT_NEXT 83
|
22 |
|
23 | #define LED PD3
|
24 |
|
25 | // Port Defines
|
26 | #define PORTLED PORTD
|
27 |
|
28 | // --------------------------------------------------------------------------------------------
|
29 | // Funktionsdeklarationen
|
30 | // --------------------------------------------------------------------------------------------
|
31 | void init_ports(void); // Initialisiert die Ports, Enable global Interrupt
|
32 | void init_timer1(void); // Initialisiert den Timer1 16-bit
|
33 |
|
34 | uint8_t get_key_press_PIND_high( uint8_t key_mask );
|
35 | uint8_t get_key_state_PIND_high( uint8_t key_mask );
|
36 | uint8_t get_key_rpt_PIND_high( uint8_t key_mask );
|
37 | uint8_t get_key_short_PIND_high( uint8_t key_mask );
|
38 | uint8_t get_key_long_PIND_high( uint8_t key_mask );
|
39 |
|
40 |
|
41 | volatile uint8_t key_state_PIND_high; // debounced and non-inverted key state: bit = 1: key pressed, liest den Zustand eines Ports ein gemäß der Maske
|
42 | volatile uint8_t key_press_PIND_high; // key press detect active high
|
43 | volatile uint8_t key_rpt_PIND_high;
|
44 |
|
45 |
|
46 | //Timer1 16-bit Compare Match B Interrupt Service Routine
|
47 | ISR (TIMER1_COMPB_vect){
|
48 | static uint8_t u8Entprellcounter;
|
49 | u8Entprellcounter++;
|
50 | if (u8Entprellcounter >= 3){ // alle 12ms Entprellfunktionen aufrufen
|
51 | // Entprellen des PIND active high
|
52 | static uint8_t ct0_PIND_high, ct1_PIND_high, rpt_PIND_high;
|
53 | uint8_t i_PIND_high;
|
54 |
|
55 | i_PIND_high = key_state_PIND_high ^ PIND; // key changed?, not inverted!
|
56 | ct0_PIND_high = ~( ct0_PIND_high & i_PIND_high ); // reset or count ct0
|
57 | ct1_PIND_high = ct0_PIND_high ^ (ct1_PIND_high & i_PIND_high); // reset or count ct1
|
58 | i_PIND_high &= ct0_PIND_high & ct1_PIND_high; // count until roll over ?
|
59 | key_state_PIND_high ^= i_PIND_high; // then toggle debounced state
|
60 | key_press_PIND_high |= key_state_PIND_high & i_PIND_high; // 0->1: key press detect
|
61 |
|
62 | if( (key_state_PIND_high & (1<<PD0)) == 0 ) // check repeat function
|
63 | rpt_PIND_high = REPEAT_START; // start delay
|
64 | if( --rpt_PIND_high == 0 ){
|
65 | rpt_PIND_high = REPEAT_NEXT; // repeat delay
|
66 | key_rpt_PIND_high |= key_state_PIND_high & (1<<PD0);
|
67 | }
|
68 |
|
69 | u8Entprellcounter = 0; // Entprellcounter nullen
|
70 | }
|
71 |
|
72 |
|
73 | OCR1B = OCR1B+((F_CPU/8000000UL)*31999); // Compare Match Register wieder vorladen, erzeugt ein Compare Match jede 4ms
|
74 |
|
75 | }
|
76 |
|
77 |
|
78 | /*Hauptprogramm Aufgaben:
|
79 |
|
80 | Das Hauptprogramm
|
81 | */
|
82 | int main(void)
|
83 | {
|
84 | init_ports();
|
85 | init_timer1();
|
86 |
|
87 | // LED einschalten, dass man sieht, dass Spannung anliegt und µC läuft
|
88 | PORTLED &= ~( 1<<LED );
|
89 | _delay_ms(300);
|
90 | PORTLED |= ( 1<<LED );
|
91 |
|
92 | while (1){
|
93 |
|
94 | if( get_key_short_PIND_high( 1<<PD0 )){
|
95 | PORTLED &= ~( 1<<LED );
|
96 | _delay_ms(300);
|
97 | PORTLED |= ( 1<<LED );
|
98 | }
|
99 |
|
100 | if( get_key_long_PIND_high( 1<<PD0 )){
|
101 | PORTLED &= ~( 1<<LED );
|
102 | _delay_ms(1000);
|
103 | PORTLED |= ( 1<<LED );
|
104 | }
|
105 |
|
106 |
|
107 | } // Ende main loop
|
108 | } // Ende Hauptprogramm
|
109 |
|
110 |
|
111 |
|
112 | // ----------------------------------------------------------------------------
|
113 | // Funktionen
|
114 | // ----------------------------------------------------------------------------
|
115 |
|
116 | /*Funktion zum Initialisierein des µC*/
|
117 | void init_ports(void) {
|
118 |
|
119 | // ===========================================================================================
|
120 |
|
121 | DDRB = 0x00;
|
122 |
|
123 | DDRC = 0x00; // Datenrichtungsregister zunächst alle Eingang
|
124 |
|
125 | DDRD = 0x00; // Datenrichtungsregister zunächst alle Eingang
|
126 | DDRD |= (1 << DDD3); // LED als Ausgang
|
127 | PORTD |= (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD4); // Pullups einschalten, LED ausschalten
|
128 |
|
129 |
|
130 | sei(); // setzt globales Interrupt enable
|
131 |
|
132 | return;
|
133 | }
|
134 |
|
135 | void init_timer1(void) {
|
136 |
|
137 | OCR1B = ((F_CPU/8000000UL)*31999); // Berechnet den Compare Wert für 4ms bei max. 16Mhz Frequenz
|
138 | TIMSK |= (1 << OCIE1B);
|
139 | TCNT1 = 0;
|
140 | TCCR1B |= (1 << CS10); // kein Prescaler, Timer1 läuft maximal durch
|
141 |
|
142 | return;
|
143 | }
|
144 |
|
145 |
|
146 | // Funktion für Tastendruck-Erkennung Tasten gegen VCC
|
147 | uint8_t get_key_press_PIND_high( uint8_t key_mask ) {
|
148 | cli(); // read and clear atomic !
|
149 | key_mask &= key_press_PIND_high; // read key(s)
|
150 | key_press_PIND_high ^= key_mask; // clear key(s)
|
151 | sei();
|
152 | return key_mask;
|
153 | }
|
154 |
|
155 | uint8_t get_key_state_PIND_high( uint8_t key_mask ){
|
156 |
|
157 | key_mask &= key_state_PIND_high;
|
158 | return key_mask;
|
159 | }
|
160 |
|
161 | uint8_t get_key_rpt_PIND_high( uint8_t key_mask )
|
162 | {
|
163 | cli(); // read and clear atomic !
|
164 | key_mask &= key_rpt_PIND_high; // read key(s)
|
165 | key_rpt_PIND_high ^= key_mask; // clear key(s)
|
166 | sei();
|
167 | return key_mask;
|
168 | }
|
169 |
|
170 | uint8_t get_key_short_PIND_high( uint8_t key_mask )
|
171 | {
|
172 | cli(); // read key state and key press atomic !
|
173 | return get_key_press_PIND_high( ~key_state_PIND_high & key_mask );
|
174 | }
|
175 |
|
176 | uint8_t get_key_long_PIND_high( uint8_t key_mask )
|
177 | {
|
178 | return get_key_press_PIND_high( get_key_rpt_PIND_high( key_mask ));
|
179 | }
|