1 | #include <avr/io.h>
|
2 | #include <stdio.h>
|
3 | #include <stdlib.h>
|
4 | #include <string.h>
|
5 | #include "main.h"
|
6 | #include "lcd.h"
|
7 | #include <avr/wdt.h>
|
8 | #include <avr/interrupt.h>
|
9 | #include <util/delay.h>
|
10 | #include <inttypes.h>
|
11 |
|
12 | #ifndef F_CPU
|
13 | #define F_CPU 7372800 // processor clock frequency
|
14 | #warning kein F_CPU definiert
|
15 | #endif
|
16 |
|
17 | #define KEY_DDR DDRC
|
18 | #define KEY_PORT PORTC
|
19 | #define KEY_PIN PINC
|
20 | #define KEY_mitte 7
|
21 | #define KEY_links 3
|
22 | #define KEY_rechts 4
|
23 | #define KEY_oben 6
|
24 | #define KEY_unten 2
|
25 | #define ALL_KEYS (1<<KEY_mitte | 1<<KEY_links | 1<<KEY_rechts | 1<<KEY_oben /*| 1<<KEY_unten*/)
|
26 |
|
27 | #define REPEAT_MASK (1<<KEY_mitte | 1<<KEY_links | 1<<KEY_rechts | 1<<KEY_oben /*| 1<<KEY_unten*/)
|
28 | #define REPEAT_START 50 // after 500ms
|
29 | #define REPEAT_NEXT 20 // every 200ms
|
30 |
|
31 | #define LED_DDR DDRD
|
32 | #define LED_PORT PORTD
|
33 | #define LED0 0
|
34 | #define LED1 1
|
35 | #define LED2 2
|
36 | #define LED3 3
|
37 | #define LED4 4
|
38 | #define LED5 5
|
39 |
|
40 | #define ADCINPUTS 8 // Anzahl der ADC Eingänge
|
41 |
|
42 | volatile uint8_t key_state; // debounced and inverted key state:
|
43 | // bit = 1: key pressed
|
44 | volatile uint8_t key_press; // key press detect
|
45 |
|
46 | volatile uint8_t key_rpt; // key long press and repeat
|
47 |
|
48 |
|
49 | void timer0()
|
50 | {
|
51 | TCCR0 = (1<<CS02)|(1<<CS00); // divide by 1024
|
52 | TCNT0 = (-72); // preload for 10ms
|
53 | TIMSK |= 1<<TOIE0; // enable timer interrupt
|
54 | }
|
55 |
|
56 | ISR( TIMER0_OVF_vect ) // every 10ms
|
57 | {
|
58 | static uint8_t ct0, ct1, rpt;
|
59 | uint8_t i;
|
60 |
|
61 | TCNT0 = (-72); // preload for 10ms
|
62 | i = key_state ^ ~KEY_PIN; // key changed ?
|
63 | ct0 = ~( ct0 & i ); // reset or count ct0
|
64 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1
|
65 | i &= ct0 & ct1; // count until roll over ?
|
66 | key_state ^= i; // then toggle debounced state
|
67 | key_press |= key_state & i; // 0->1: key press detect
|
68 |
|
69 | if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
|
70 | rpt = REPEAT_START; // start delay
|
71 | if( --rpt == 0 )
|
72 | {
|
73 | rpt = REPEAT_NEXT; // repeat delay
|
74 | key_rpt |= key_state & REPEAT_MASK;
|
75 | }
|
76 | }
|
77 |
|
78 | ///////////////////////////////////////////////////////////////////
|
79 | //
|
80 | // check if a key has been pressed. Each pressed key is reported
|
81 | // only once
|
82 | //
|
83 | uint8_t get_key_press( uint8_t key_mask )
|
84 | {
|
85 | cli(); // read and clear atomic !
|
86 | key_mask &= key_press; // read key(s)
|
87 | key_press ^= key_mask; // clear key(s)
|
88 | sei();
|
89 | return key_mask;
|
90 | }
|
91 |
|
92 | ///////////////////////////////////////////////////////////////////
|
93 | //
|
94 | // check if a key has been pressed long enough such that the
|
95 | // key repeat functionality kicks in. After a small setup delay
|
96 | // the key is reported being pressed in subsequent calls
|
97 | // to this function. This simulates the user repeatedly
|
98 | // pressing and releasing the key.
|
99 | //
|
100 | uint8_t get_key_rpt( uint8_t key_mask )
|
101 | {
|
102 | cli(); // read and clear atomic !
|
103 | key_mask &= key_rpt; // read key(s)
|
104 | key_rpt ^= key_mask; // clear key(s)
|
105 | sei();
|
106 | return key_mask;
|
107 | }
|
108 |
|
109 | ///////////////////////////////////////////////////////////////////
|
110 | //
|
111 | // check if a key is pressed right now
|
112 | //
|
113 | uint8_t get_key_state( uint8_t key_mask )
|
114 | {
|
115 | key_mask &= key_state;
|
116 | return key_mask;
|
117 | }
|
118 |
|
119 | ///////////////////////////////////////////////////////////////////
|
120 | //
|
121 | uint8_t get_key_short( uint8_t key_mask )
|
122 | {
|
123 | cli(); // read key state and key press atomic !
|
124 | return get_key_press( ~key_state & key_mask );
|
125 | }
|
126 |
|
127 | ///////////////////////////////////////////////////////////////////
|
128 | //
|
129 | uint8_t get_key_long( uint8_t key_mask )
|
130 | {
|
131 | return get_key_press( get_key_rpt( key_mask ));
|
132 | }
|
133 |
|
134 |
|
135 | void declaration()
|
136 | {
|
137 | /* WDTCR = (1<<WDTOE);
|
138 | WDTCR &= ~(1<<WDE); // Watchdog deaktivieren */
|
139 | DDRB = 0xFF; // Blaue LED: Ausgang
|
140 | PORTB &= ~(1<< PB0);
|
141 | DDRC = 0x00; // Eingänge
|
142 | DDRC = ((1 << DDC0) | (1 << DDC1)) ; // PC0-1 Ausgang
|
143 | PORTC = 0xFF;
|
144 | PORTC &= ~((1<<PC0) | (1 <<PC1));
|
145 |
|
146 | DDRD = 0xFF; // Alle Pins von Port D als Ausgang
|
147 | PORTD = (0<<PD0)| (0<<PD1)|(0<<PD2)|(0<<PD3)|(0<<PD4)|(0<<PD5)|(0<<PD6);
|
148 |
|
149 | DDRA = 0xFF; // LCD Ausgänge
|
150 | DDRA &= ~((1<<PA6) | (1<<PA7)); // ADC Eingänge
|
151 | }
|
152 |
|
153 | int main( void )
|
154 | {
|
155 |
|
156 |
|
157 | KEY_DDR &= ~ALL_KEYS; // configure key port for input
|
158 | KEY_PORT |= ALL_KEYS; // and turn on pull up resistors
|
159 |
|
160 | LED_PORT = 0xFF;
|
161 | LED_DDR = 0xFF;
|
162 |
|
163 | // Configure debouncing routines
|
164 |
|
165 |
|
166 |
|
167 | /* IOs initialisieren */
|
168 |
|
169 | declaration();
|
170 |
|
171 |
|
172 |
|
173 | timer0(); // 10ms
|
174 | sei();
|
175 |
|
176 | while(1)
|
177 | {
|
178 |
|
179 |
|
180 | if(get_key_short(KEY_links)) PORTD ^= (1<<PD0);
|
181 | if(get_key_short(KEY_rechts)) PORTD ^= (1<<PD1);
|
182 | if(get_key_short(KEY_oben)) PORTD ^= (1<<PD2);
|
183 | if(get_key_short(KEY_unten)) PORTD ^= (1<<PD3);
|
184 | if(get_key_short(KEY_mitte)) PORTD ^= (1<<PD4);
|
185 |
|
186 |
|
187 | if(get_key_long(KEY_links)) PORTD ^= (1<<PD0);
|
188 | if(get_key_long(KEY_rechts)) PORTD ^= (1<<PD1);
|
189 | if(get_key_long(KEY_oben)) PORTD ^= (1<<PD2);
|
190 | if(get_key_short(KEY_unten)) PORTD ^= (1<<PD3);
|
191 | if(get_key_long(KEY_mitte)) PORTD ^= (1<<PD4);
|
192 | }
|
193 | }
|