1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
## Laboration 1
### Givna subrutiner
- `printchar`
- `inituart`
- `initgpioe`
- `initgpiof`
### Begränsningar
Du får enbart göra en läsning ifrån `0x2000100-0x20001003` och `0x20001010-0x2001013` i `checkcode`.
### Subrutiner att skriva
#### printstring
Skriver ut den textsträng som r4 pekar på på terminalen med hjälp av `printchar`.
```asm
; inargument: pekare till strängen i r4
; längd på strängen i r5
; utargument: inga
;
; funktion: skriver ut strängen mha subrutinen printchar
;
; förstör r0 och r1
printstring:
mov r1,#0x00
printstring_print_next:
mov r0,[r4,r6] ; indirekt register med register offset
push lr
bl printchar
pop lr
add r1,#0x01 ; next char
; have we printed all characters?
cmp r5,r1
bne printstring_print_next
; yes, so return
bx lr
```
#### deactivatealarm
Får lysdioden att lysa grönt.
```asm
; inargument: inga
; utargument: inga
;
; funktion: tänder grön lysdiod (bit 3 = 1, bit 2 = 0, bit 1 = 0)
;
; förstör r0 och r1
deactivatealarm:
; read current data
mov r0,#GPIOF_GPIODATA
ldr r1,[r0]
; set bit 3 to 1
orr r1,r1,(0x04) ; 0x04 = 0000_0100
; set bit 2 and 1 to 0
and r1,r1,(0xfc) ; 0xfc = 1111_1100
; write new data
str r1,[r0]
bx lr
```
#### activatealarm
Får lysdioden att lysa rött.
```asm
; inargument: inga
; utargument: inga
;
; funktion: tänder röd lysdiod (bit 3 = 0, bit 2 = 0, bit 1 = 1)
;
; förstör r0 och r1
activatealarm:
; read current data
mov r0,#GPIOF_GPIODATA
ldr r1,[r0]
; set bit 1 to 1
orr r1,r1,(0x01) ; 0x01 = 0000_0001
; set bit 3 and 2 to 0
and r1,r1,(0xf9) ; 0xf9 = 1111_1001
; write new data
str r1,[r0]
bx lr
```
#### getkey
Vänta på att användaren trycker på en tangent. Se till att returnera först när användaren slutar trycka på tangenten.
```asm
; inargument: inga
; utargument: tryckt knapp i r4
;
; förstör r0, r1
getkey:
mov r0,#GPIOE_GPIODATA
; wait for strobe
getkey_strobe_check:
ldr r1,[r0]
mov r4,r1
ands r1,r1,#0x10 ; 0x10 = 0001_0000
bne getkey_strobe_check
; strobe is high, so put char in r4
ands r4,r4,#0x0f ; 0x0f = 0000_1111
bx lr
```
#### addkey
Lägg till ett tecken i inbuffern genom att skifta buffern framåt ett steg.
Exempel:
```
Adress Ursprungstillstånd Efter att addkey anropats med 1 i r4
0x20001000 0x05 0x01
0x20001001 0x06 0x05
0x20001002 0xFF 0x06
0x20001003 0xFF 0xFF
```
```asm
; inargument: vald tangent i r4
; utargument: inga
;
; funktion: flyttar innehållet på 0x20001000-0x20001002 framåt en byte
; till 0x20001001-0x20001003.
; lagrar sedan innehållet i r4 på 0x20001000
;
; förstör r0
addkey:
; ..02 -> ..03
ldrb r0,#0x20001002
strb r0,#0x20001003
; ..01 -> ..02
ldrb r0,#0x20001001
strb r0,#0x20001002
; ..00 -> ..01
ldrb r0,#0x20001000
strb r0,#0x20001001
; r4 -> ..00
strb r4,#0x20001000
bx lr
```
#### clearinput
Rensar inbuffern genom att lägga in en ogiltig kod.
```asm
; inargument: inga
; utargument: inga
;
; funktion: sätter innehållet på 0x20001000-0x20001003 till 0xFF
;
; förstör r0
clearinput:
mov r0,#0xff
strb r0,#0x20001000
strb r0,#0x20001001
strb r0,#0x20001002
strb r0,#0x20001003
bx lr
```
#### checkcode
Kollar om den kod som ligger i inbuffern på 0x20001000 är korrekt.
```asm
CODE_LENGTH .equ 0x04
; inargument: inga
; utargument: returnerar 1 i r4 om koden var korrekt,
; annars 0 i r4
;
; funktion: tänder grön lysdiod (bit 3 = 1, bit 2 = 0, bit 1 = 0)
;
; förstör r0, r1 och r2
checkcode:
mov r0,#0x00 ; index
mov r1,#0x20001000 ; to check
mov r2,#0x20001010 ; key
checkcode_next:
; check length
cmp r0,#CODE_LENGTH
beq checkcode_correct
; compare next byte
cmp [r1,r0],[r2,r0]
beq checkcode_next ; equal, check next
b checkcode_incorrect ; not equal, so incorrect
checkcode_incorrect:
mov r4,#0x00
b checkcode_exit
checkcode_correct:
mov r4,#0x01
b checkcode_exit
checkcode_exit:
bx lr
```
|