summaryrefslogtreecommitdiff
path: root/rrxing.S
blob: 61fb41c1fc11c0509b4fb0cdd9f20cda67c624f8 (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
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"