1 | .include "m48def.inc"
|
2 |
|
3 | .def iwr0 = r1
|
4 | .def iwr1 = r2
|
5 |
|
6 | .def key_old = r3
|
7 | .def key_state = r4
|
8 | .def key_press = r5
|
9 |
|
10 | .def temp1 = r17
|
11 | .def sreg_save = r18
|
12 |
|
13 |
|
14 | .equ key_pin = PINB
|
15 | .equ key_port = PORTB
|
16 | .equ key_ddr = DDRB
|
17 |
|
18 | .def leds = r19
|
19 | .equ led_port = PORTD
|
20 | .equ led_ddr = DDRD
|
21 |
|
22 | .org 0x0000
|
23 | ;rcall EEPROM_read
|
24 | rjmp init
|
25 |
|
26 | .org OVF0addr
|
27 | rjmp timer_overflow0
|
28 |
|
29 | ;
|
30 | ; *****************************************************************************
|
31 | ;
|
32 | ; Initialisierung
|
33 | ; Alle Komponenten auf die Startbedingungen einstellen
|
34 | ;
|
35 | init:
|
36 | ;
|
37 | ; Stackpointer
|
38 | ;
|
39 | ldi temp1, HIGH(RAMEND)
|
40 | out SPH, temp1
|
41 | ldi temp1, LOW(RAMEND) ; Stackpointer initialisieren
|
42 | out SPL, temp1
|
43 | ;
|
44 | ; Ausgänge
|
45 | ;
|
46 | ldi temp1, 0xFF
|
47 | out led_ddr, temp1
|
48 | ;
|
49 | ; Eingänge
|
50 | ;
|
51 | ldi temp1, 0xFF ; Tasten sind auf Eingang
|
52 | out key_port, temp1 ; Pullup Widerstände ein
|
53 | ;
|
54 | ; Timer für die Tastenabfrage
|
55 | ;
|
56 | ldi temp1, 1<<CS02 | 1<<CS00 ; Timer mit Vorteiler 1024
|
57 | out TCCR0, temp1
|
58 | ldi temp1, 1<<TOIE0 ; Timer Overflow Interrupt einrichten
|
59 | out TIMSK, temp1
|
60 |
|
61 | clr key_old ; die Register für die Tastenauswertung im
|
62 | clr key_state ; Timer Interrupt initialisieren
|
63 | clr key_press
|
64 |
|
65 | sei ; und los gehts: Timer frei
|
66 |
|
67 | ;
|
68 | ; aus dem EEPROM den letzten Zustand wiederherstellen
|
69 |
|
70 | ldi ZL,low(daten)
|
71 | ldi ZH,high(daten)
|
72 | rcall EEPROM_read ; Byte ist in r16
|
73 |
|
74 | mov leds, r16
|
75 | out led_port, leds
|
76 |
|
77 | ;
|
78 | ; Alles ist eingerichtet. Jetzt gehts mit der eigentlichen Arbeit los
|
79 | ;
|
80 | main:
|
81 | cli ;
|
82 | mov temp1, key_press ; Einen ev. Tastendruck merken und ...
|
83 | clr key_press ; Tastendruck zurücksetzen
|
84 | sei
|
85 |
|
86 | cpi temp1, 0 ; Tastendruck auswerten. Wenn eine von 8 Tasten
|
87 | breq main ; gedrückt worden wäre, wäre ein entsprechendes
|
88 | ; Bit in key_press gesetzt gewesen
|
89 |
|
90 | eor leds, temp1 ; Die zur Taste gehörende Led umschalten
|
91 | out led_port, leds
|
92 |
|
93 | ; und den neuen Zustand im EEPROM ablegen
|
94 | ; das Z-Register ist noch vom Lesen an
|
95 | ; der richtigen Stelle
|
96 | mov r16, leds
|
97 | rcall EEPROM_write
|
98 |
|
99 | rjmp main
|
100 |
|
101 | ;
|
102 | ; *****************************************************************************
|
103 | ;
|
104 | ; Timer Overflow
|
105 | ; wird regelmässig aufgerufen und hat die Aufgabe die Tasten auszuwerten
|
106 | ;
|
107 | ; Eine vollständig gedrückte Taste wird im Register key_press mit einem
|
108 | ; 1 Bit vermerkt. Der Benutzer ist selbst dafür zuständig, dieses Bit
|
109 | ; wieder zu löschen
|
110 | ;
|
111 | timer_overflow0: ; Timer Overflow Interrupt
|
112 |
|
113 | push r0 ; temporäre Register sichern
|
114 | in r0, SREG
|
115 | push r0
|
116 | push iwr0
|
117 | push iwr1
|
118 |
|
119 | get8key: ;/old state iwr1 iwr0
|
120 | mov iwr0, key_old ;00110011 10101010 00110011
|
121 | in key_old, key_pin ;11110000
|
122 | eor iwr0, key_old ; 11000011
|
123 | com key_old ;00001111
|
124 | mov iwr1, key_state ; 10101010
|
125 | or key_state, iwr0 ; 11101011
|
126 | and iwr0, key_old ; 00000011
|
127 | eor key_state, iwr0 ; 11101000
|
128 | and iwr1, iwr0 ; 00000010
|
129 | or key_press, iwr1 ; gedrückte Taste merken
|
130 | ;
|
131 | ;
|
132 | pop iwr1 ; Register wiederherstellen
|
133 | pop iwr0
|
134 | pop r0
|
135 | out SREG, r0
|
136 | pop r0
|
137 | reti
|
138 |
|
139 | ;
|
140 | ; *****************************************************************************
|
141 | ;
|
142 | ; Lesefunktion aus dem EEPROM
|
143 | ;
|
144 | ; Die Adresse von der gelesen werden soll, wird im Z-Register übergeben (r30/r31)
|
145 | ;
|
146 | ; Das gelesene Byte bekommt man im Register r16 zurückgeliefert
|
147 | ;
|
148 | EEPROM_read:
|
149 | sbic EECR,EEWE ; prüfe ob der vorherige Schreibzugriff
|
150 | ; beendet ist
|
151 | rjmp EEPROM_read ; nein, nochmal prüfen
|
152 |
|
153 | out EEARH, ZH ; Adresse laden
|
154 | out EEARL, ZL
|
155 | sbi EECR, EERE ; Lesevorgang aktivieren
|
156 | in r16, EEDR ; Daten in CPU Register kopieren
|
157 | ;out led_port, leds
|
158 | ret
|
159 |
|
160 | ;
|
161 | ; *****************************************************************************
|
162 | ;
|
163 | ; Schreibfunktion ins EEPROM
|
164 | ;
|
165 | ; Die Adresse an die geschrieben werden soll, wird im Z-Register übergeben (r30/r31)
|
166 | ; Das zu schreibende Byte wird im Register r16 übergeben
|
167 | ;
|
168 | EEPROM_write:
|
169 | sbic EECR, EEWE ; prüfe ob der letzte Schreibvorgang beendet ist
|
170 | rjmp EEPROM_write ; wenn nein, nochmal prüfen
|
171 |
|
172 | out EEARH, ZH ; Adresse schreiben
|
173 | out EEARL, ZL ;
|
174 | out EEDR, r16 ; Daten schreiben
|
175 | in sreg_save,sreg ; SREG sichern
|
176 | cli ; Interrupts sperren, die nächsten
|
177 | ; zwei Befehle dürfen NICHT
|
178 | ; unterbrochen werden
|
179 | sbi EECR,EEMWE ; Schreiben vorbereiten
|
180 | sbi EECR,EEWE ; Und los !
|
181 | out sreg, sreg_save ; SREG wieder herstellen
|
182 | ret
|
183 |
|
184 |
|
185 | ; Daten im EEPROM definieren
|
186 | ;
|
187 | .eseg
|
188 | ;
|
189 | daten:
|
190 | .db 0b00000000
|