summaryrefslogtreecommitdiff
path: root/assembly/crosswalk/crosswalk.S
blob: 769e9b22d7aa75c90e9e4f3dfbc440010a3ee4c8 (plain)
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
la t0,handler
csrw mtvec,t0 # Set up trap handler
li t0,0x400
csrc mstatush,t0 # Turn off MDT
li t0,0x20000
csrw mie,t0 # Mask all interrupts except digilines
csrw mip,zero # Clear any pending interrupts
csrsi mstatus,0x8 # Turn on MIE to enable interrupts

la t0,pedwaiting
sb zero,0(t0) # Clear the pedestrian waiting flag (really it should already be clear, this handles the case of a program restart)

restart:
la a0,lightchannel
la a1,greenmsg
li a7,129
ecall # Light -> green

la a0,pedchannel
la a1,redmsg
li a7,129
ecall # Ped -> red (don't walk)

li a0,10
call sleep

waitloop:
la t0,pedwaiting
lb t0,0(t0)
bnez t0,startsequence # Check if someone is waiting
wfi # Otherwise wait for something to happen
j waitloop

startsequence:
la a0,lightchannel
la a1,yellowmsg
li a7,129
ecall # Light -> yellow

li a0,3
call sleep

la a0,lightchannel
la a1,redmsg
li a7,129
ecall # Light -> red

li a0,2
call sleep

la a0,pedchannel
la a1,greenmsg
li a7,129
ecall # Ped -> green (walk)

li a0,5
call sleep

la a0,pedchannel
la a1,flashredmsg
li a7,129
ecall # Ped -> flashing red (flashing don't walk)

la t0,pedwaiting
sb zero,0(t0) # Clear the detection flag at this point too

li a0,10
call sleep

la a0,pedchannel
la a1,redmsg
li a7,129
ecall # Ped -> red (don't walk)

li a0,1
call sleep

la a0,lightchannel
la a1,redyellowmsg
li a7,129
ecall # Light -> red+yellow

li a0,1
call sleep

j restart # This will turn the light green before going back to waiting


sleep:
csrr t0,time # Only using 32 bits here, this will have problems after 136ish years
add a0,t0,a0
sleep_loop:
pause
csrr t0,time
blt t0,a0,sleep_loop
ret



.align 4
handler:
csrrw x31,mscratch,x31 # Free up x31 to hold the context address
la x31,hcontext # Using x register numbers here since trap handlers don't use the usual calling convention
sw x1,0(x31) # Save all the registers to the context
sd x2,4(x31) # Two at a time since we have Zilsd/Zclsd
sd x4,12(x31)
sd x6,20(x31)
sd x8,28(x31)
sd x10,36(x31)
sd x12,44(x31)
sd x14,52(x31)
sd x16,60(x31)
sd x18,68(x31)
sd x20,76(x31)
sd x22,84(x31)
sd x24,92(x31)
sd x26,100(x31)
sd x28,108(x31)
sw x30,116(x31)
csrr x30,mscratch # Get the old x31 value back into a register
sw x30,120(x31) # and write that back out too

csrr t0,mcause # Read why the trap occurred

li t1,0x80000011 # Interrupt 17 = digilines
beq t0,t1,handler_digilines

j handler_other # Something else

handler_digilines:
li a7,135
la a0,channelbuf
li a1,21
la a2,msgbuf
li a3,21
ecall # Read what the event was

la t0,channelbuf
lb t0,0(t0)
li t1,'b'
bne t0,t1,handler_notbutton # Check if the channel started with 'b' (not going to bother checking the rest)

la t0,pedwaiting
li t1,1
sb t1,0(t0) # Set the pedestrian waiting flag

handler_notbutton:

li a7,133
ecall # Check if there are more messages to process
bnez a0,handler_digilines

csrw mip,zero # Clear out all pending interrupts
la x31,hcontext # x numbers here for the same reason as during the save
lw x1,0(x31) # Load all of the registers from the context
ld x2,4(x31) # Two at a time since we have Zilsd/Zclsd
ld x4,12(x31)
ld x6,20(x31)
ld x8,28(x31)
ld x10,36(x31)
ld x12,44(x31)
ld x14,52(x31)
ld x16,60(x31)
ld x18,68(x31)
ld x20,76(x31)
ld x22,84(x31)
ld x24,92(x31)
ld x26,100(x31)
ld x28,108(x31)
ld x30,116(x31)
mret # Return to the program

handler_other:
li a7,4
la a0,unimplementedmsg
ecall # Display unimplemented trap message

csrr a0,mcause # Read what the cause was
li a7,1
ecall # Tell the user

li a7,10
ecall # Then halt


hcontext: .skip 32*4
unimplementedmsg: .asciz "Unimplemented trap!\nmcause: "
channelbuf: .asciz "                    "
msgbuf: .asciz "                    "

lightchannel: .asciz "light"
pedchannel: .asciz "ped"
redmsg: .asciz "RED"
yellowmsg: .asciz "YELLOW"
greenmsg: .asciz "GREEN"
flashredmsg: .asciz "FLASHRED"
redyellowmsg: .asciz "REDYELLOW"
pedwaiting: .byte 0