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
|
li a7,134 # Clear digilines buffer
ecall
restart:
# Hardware initialization
# Make sure light is off
li a7,129 # Send digilines message
la a0,lightchannel
la a1,lightoffmsg
ecall
# Make sure bell is off
li a7,129 # Send digilines message
la a0,bellchannel
la a1,belloffmsg
ecall
# Make sure gate is up
li a7,129 # Send digilines message
la a0,gatechannel
la a1,gateupmsg
ecall
receiveloop:
li a7,133 # Get digilines buffer level
ecall
beq a0,x0,receiveloop # If no messages yet, restart the loop
li a7,135 # Read digilines message
la a0,channelbuf
li a1,16 # Channel buffer size
la a2,msgbuf
li a3,16 # Message buffer size
ecall
# Check if it's the right channel
la a0,channelbuf
la a1,detectchannel
call strcmp
beq a0,x0,receiveloop # Not the right channel, ignore it
# Turn the light yellow
li a7,129 # Send digilines message
la a0,lightchannel
la a1,lightyellowmsg
ecall
# Wait 1 second
li a0,1
call sleep
# Turn the bell on
li a7,129 # Send digilines message
la a0,bellchannel
la a1,bellonmsg
ecall
# Wait 2 seconds
li a0,2
call sleep
# Turn the light red
li a7,129 # Send digilines message
la a0,lightchannel
la a1,lightredmsg
ecall
# Wait 3 seconds
li a0,3
call sleep
# Lower the gate
li a7,129 # Send digilines message
la a0,gatechannel
la a1,gatedownmsg
ecall
# Wait 5 seconds
li a0,5
call sleep
# Turn the bell off
li a7,129 # Send digilines message
la a0,bellchannel
la a1,belloffmsg
ecall
waitlonger:
# Wait 10 seconds
li a0,10
call sleep
# Check if any more trains have been detected
receiveloop2:
li a7,133 # Get digilines buffer level
ecall
beq a0,x0,raise # If no messages yet, go ahead with timing out
# If there is a message, check if it's a train
li a7,135 # Read digilines message
la a0,channelbuf
li a1,16 # Channel buffer size
la a2,msgbuf
li a3,16 # Message buffer size
ecall
# Check if it's the right channel
la a0,channelbuf
la a1,detectchannel
call strcmp
beq a0,x0,receiveloop2 # Not the right channel, ignore this message and go on to the next
# If it is the right channel, then get rid of the rest of the messages (if any)
li a7,134 # Clear digilines buffer
ecall
j waitlonger # And go wait another 10 seconds
raise:
# Raise the gate
li a7,129 # Send digilines message
la a0,gatechannel
la a1,gateupmsg
ecall
# Wait 2 seconds
li a0,2
call sleep
# Turn the light off
li a7,129 # Send digilines message
la a0,lightchannel
la a1,lightoffmsg
ecall
# And go wait for the next train
j restart
sleep:
# Expects a number of seconds in a0
# Uses t0
rdtime t0
add a0,t0,a0
sleep_loop:
rdtime t0
bltu t0,a0,sleep_loop
ret
strcmp:
# Expects string pointers in a0 and a1
# Compares until a NUL is reached on the first string
# Uses t0, t1, and t2
# Returns a0=1 if strings match, a0=0 otherwise
li t0,0 # t0 is the loop counter
strcmp_loop:
# Calculate addresses
add t1,a0,t0 # t1 is the pointer for the first string
add t2,a1,t0 # t2 is the pointer for the second string
# Read the bytes from each string
lb t1,0(t1)
lb t2,0(t2)
# Increment the loop counter
addi t0,t0,1
# And compare
bne t1,t2,strcmp_mismatch
# Check if a terminator was reached yet, keep going otherwise
li t2,0
bne t1,t2,strcmp_loop
# If we got here they match
li a0,1
ret
strcmp_mismatch:
li a0,0
ret
channelbuf: .ascii " "
msgbuf: .ascii " "
lightchannel: .asciz "light"
bellchannel: .asciz "bell"
gatechannel: .asciz "gate"
lightoffmsg: .asciz "OFF"
lightyellowmsg: .asciz "YELLOW"
lightredmsg: .asciz "RED"
bellonmsg: .asciz "on"
belloffmsg: .asciz "off"
gateupmsg: .asciz "up"
gatedownmsg: .asciz "down"
detectchannel: .asciz "detect"
|