/
interrupt.asm
222 lines (205 loc) · 4.03 KB
/
interrupt.asm
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
;; contextSwitch [System]
;; Triggers a context switch early. This will transfer control from your thread to
;; another and eventaully return to yours with interrupts enabled.
contextSwitch:
di
push af
push bc
push de
push hl
push ix
push iy
exx
ex af, af'
push af
push bc
push de
push hl
jr doContextSwitch
sysInterrupt:
di
push af
push bc
push de
push hl
push ix
push iy
exx
ex af, af'
push af
push bc
push de
push hl
#ifdef USB
jp usbInterrupt
interruptResume:
#endif
in a, (PORT_INT_TRIG)
bit BIT_INT_TRIG_ON, a
jr nz, intHandleON
bit BIT_INT_TRIG_TIMER1, a
jr nz, intHandleTimer1
bit BIT_INT_TRIG_TIMER2, a
jr nz, intHandleTimer2
bit BIT_INT_TRIG_LINK, a
jr nz, intHandleLink
jr contextSwitch
intHandleON:
in a, (PORT_INT_MASK)
res BIT_INT_ON, a
out (PORT_INT_MASK), a
set BIT_INT_ON, a
out (PORT_INT_MASK), a
; Check for special keycodes
jp handleKeyboard
intHandleTimer1:
in a, (PORT_INT_MASK)
res BIT_INT_TIMER1, a
out (PORT_INT_MASK), a
set BIT_INT_TIMER1, a
out (PORT_INT_MASK), a
; Timer 1 interrupt
doContextSwitch:
ld a, (currentThreadIndex)
add a, a
add a, a
add a, a
ld hl, threadTable + 3
add a, l
ld l, a
ex de, hl
ld hl, 0
add hl, sp
ex de, hl
; Save stack pointer
ld (hl), e
inc hl
ld (hl), d
contextSwitch_manual:
ld a, (activeThreads)
or a \ jr z, noThreads ; Error out when there are no active threads
ld c, a \ inc c
contextSwitch_search:
dec c
xor a
cp c
jr z, noActiveThreads
ld a, (currentThreadIndex)
inc a \ ld (currentThreadIndex), a
ld b, a
ld a, (activeThreads)
dec a \ cp b
jr nc, _
xor a
ld b, a
ld (currentThreadIndex), a
_: ld a, b
add a, a
add a, a
add a, a
ld hl, threadTable + 5
add a, l
ld l, a
ld a, (hl)
bit 1, a ; May be suspended
jr nz, _
bit 2, a
jr nz, contextSwitch_search ; Suspended
_: dec hl
ld d, (hl)
dec hl
ld e, (hl)
ex de, hl
ld sp, hl
jr sysInterruptDone
noThreads:
ld a, panic_no_threads
jp panic
noActiveThreads:
ld a, panic_no_active_threads
set 7, a
jp panic
intHandleTimer2:
in a, (PORT_INT_MASK)
res BIT_INT_TIMER2, a
out (PORT_INT_MASK), a
set BIT_INT_TIMER2, a
out (PORT_INT_MASK), a
; Timer 2 interrupt
jr sysInterruptDone
intHandleLink:
in a, (PORT_INT_MASK)
res BIT_INT_LINK, a
out (PORT_INT_MASK), a
set BIT_INT_LINK, a
out (PORT_INT_MASK), a
; Link interrupt
sysInterruptDone:
pop hl
pop de
pop bc
pop af
exx
ex af, af'
pop iy
pop ix
pop hl
pop de
pop bc
pop af
ei
ret
handleKeyboard:
call getKey_skipCheck
call flushKeys_skipCheck
cp kK
jr z, handleOnK
cp kR
jp z, reboot
cp kMODE
jr z, handleOnMODE
#ifdef DEBUG
cp kPRGM
jr z, handleOnPRGM
#endif
jr sysInterruptDone
handleOnMODE:
ld de, init
call launchProgram
ld h, 1
call setInitialA
jr sysInterruptDone
handleOnK:
ld a, (hwLockLCD)
call killThread
jp contextSwitch_manual
#ifdef DEBUG
handleOnPRGM:
rst 0x30
jp sysInterruptDone
#endif
#ifdef USB
usbInterrupt:
in a, (0x55) ; USB Interrupt status
bit BIT_USB_INT_BUS, a
jr z, usbUnknownEvent
bit BIT_USB_INT_LINE, a
jr z, usbLineEvent
bit BIT_USB_INT_PROTOCOL, a
jr z, usbProtocolEvent
jp interruptResume
usbUnknownEvent:
jp interruptResume
usbLineEvent:
in a, (PORT_USB_LINE) ; USB Line Events
xor 0xFF
out (PORT_USB_LINE_MASK), a ; Acknowledge interrupt and disable further interrupts
jp interruptResume
usbProtocolEvent:
in a, (PORT_USB_WRPIPE1)
in a, (PORT_USB_WRPIPE2)
in a, (PORT_USB_RDPIPE1)
in a, (PORT_USB_RDPIPE2)
in a, (PORT_USB_MISC_EVENTS) ; Merely reading from these will acknowledge the interrupt
jp interruptResume
#endif