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"
