summaryrefslogtreecommitdiff
path: root/assembly/rrxing2/ui.S
diff options
context:
space:
mode:
authorcheapie <cheapiephp@gmail.com>2026-11-04 19:34:16 -0600
committercheapie <cheapiephp@gmail.com>2026-11-04 19:34:16 -0600
commit203798c72f10d003f16485b1ffb2758b9bcfa58c (patch)
tree9a2ce6d1ab689bff19ea71b0379836645905a286 /assembly/rrxing2/ui.S
parent6fc47c5b8ff009bbae39ac11b57909bff6fb9039 (diff)
downloadrvcontroller-203798c72f10d003f16485b1ffb2758b9bcfa58c.tar
rvcontroller-203798c72f10d003f16485b1ffb2758b9bcfa58c.tar.gz
rvcontroller-203798c72f10d003f16485b1ffb2758b9bcfa58c.tar.bz2
rvcontroller-203798c72f10d003f16485b1ffb2758b9bcfa58c.tar.xz
rvcontroller-203798c72f10d003f16485b1ffb2758b9bcfa58c.zip
Add work-in-progress rrxing2 program
Diffstat (limited to 'assembly/rrxing2/ui.S')
-rw-r--r--assembly/rrxing2/ui.S452
1 files changed, 452 insertions, 0 deletions
diff --git a/assembly/rrxing2/ui.S b/assembly/rrxing2/ui.S
new file mode 100644
index 0000000..ef3734d
--- /dev/null
+++ b/assembly/rrxing2/ui.S
@@ -0,0 +1,452 @@
+mainloop:
+la ra,uidrawend # Will call a function to draw the current page, but it will return to the end instead of here
+la t0,uipage
+lbu t0,0(t0)
+
+beqz t0,uidrawidle # Page 0: Idle screen
+
+li t1,1
+beq t0,t1,uidrawmainmenu # Page 1: Main menu
+
+li t1,2
+beq t0,t1,uidrawcountryselect # Page 2: Country selection
+
+li t1,3
+beq t0,t1,uidrawadjusttiming # Page 3: Timing adjustments
+
+li t1,4
+beq t0,t1,uidrawgatedropdelay # Page 4: Gate drop delay adjustment
+
+li t1,5
+beq t0,t1,uidrawinitialtime # Page 5: Initial active time adjustment
+
+li t1,6
+beq t0,t1,uidrawextensiontime # Page 6: Extension time adjustment
+
+li t1,7
+beq t0,t1,uidrawinvalidinput # Page 7: Invalid (time) input
+
+j uidrawunknown
+
+uidrawend:
+wfi # Program is entirely interrupt-driven, so wait for something to happen
+j mainloop
+
+handler_console:
+li t0,262144 # 2^18, value of MCIP bit
+csrc mip,t0
+la ra,uihandlingend # Will call a function to handle input for the current page, but it will return to the end instead of here
+la t0,uipage
+lbu t0,0(t0)
+
+beqz t0,uihandleidle # Page 0: Idle screen
+
+li t1,1
+beq t0,t1,uihandlemainmenu # Page 1: Main menu
+
+li t1,2
+beq t0,t1,uihandlecountryselect # Page 2: Country selection
+
+li t1,3
+beq t0,t1,uihandleadjusttiming # Page 3: Timing adjustments
+
+li t1,4
+beq t0,t1,uihandlegatedropdelay # Page 4: Gate drop delay adjustment
+
+li t1,5
+beq t0,t1,uihandleinitialtime # Page 5: Initial active time adjustment
+
+li t1,6
+beq t0,t1,uihandleextensiontime # Page 6: Extension time adjustment
+
+li t1,7
+beq t0,t1,uihandleinvalidinput # Page 7: Invalid (time) input
+
+uihandlingend:
+li a7,131
+ecall # Drop anything else the user may have typed
+j handler_epilogue
+
+copystring:
+# Destination pointer in a0, source pointer in a1, copies until null is reached (but doesn't copy the null), not very optimized
+lb t0,0(a1)
+beqz t0,1f
+sb t0,0(a0)
+addi a0,a0,1
+addi a1,a1,1
+j copystring
+1: ret
+
+uidrawidle:
+cm.push {ra},-16
+la a0,uiidle+44
+la a3,uiidle
+la t0,currstate # Check if currently running or not
+lbu t0,0(t0)
+andi t0,t0,0xf
+beqz t0,1f
+la a0,uiactive+44 # If so, then show the active message instead
+la a3,uiactive
+1: la a1,uide
+la t0,country
+lb t0,0(t0)
+li t1,1
+bne t0,t1,1f
+la a1,uiuk
+1: li t1,2
+bne t0,t1,1f
+la a1,uius
+1: call copystring
+mv a0,a3
+li a7,4
+ecall
+cm.popret {ra},16
+
+uihandleidle:
+cm.push {ra},-16
+li a7,132
+ecall # Read one character of input
+li t0,'m'
+bne a0,t0,1f # If it was 'm'...
+la t0,uipage
+li t1,1
+sb t1,0(t0) # ...go to the main menu (page 1)
+1: li t0,'a'
+bne a0,t0,1f # If it was 'a', then start the sequence now
+la t0,currstate
+lbu t0,0(t0)
+andi t0,t0,0xf
+bnez t0,1f # Unless it's already running, that is
+la t1,country
+lb t1,0(t1) # Read current country setting
+slli t1,t1,4 # Multiply by 16 to get the offset into the state table
+addi t1,t1,1 # And add 1 to get to the first non-idle state
+la t0,currstate
+sb t1,0(t0) # Update state in RAM to the first state in the current country
+la t0,states
+sh2add t0,t1,t0 # Calculate the proper offset in the list of pointers (state number * 4 + base address)
+lw t0,0(t0) # Load the pointer
+jalr ra,t0,0 # And call that function
+1: cm.popret {ra},16
+ret
+
+uidrawmainmenu:
+la a0,uimainmenu
+li a7,4
+ecall
+ret
+
+uihandlemainmenu:
+li a7,132
+ecall # Read one character of input
+li t0,'1'
+bne a0,t0,1f
+la t1,uipage
+li t2,2
+sb t2,0(t1) # User entered '1', go to country selection (page 2)
+1: li t0,'2'
+bne a0,t0,1f
+la t1,uipage
+li t2,3
+sb t2,0(t1) # User entered '2', go to timing adjustment (page 3)
+1: li t0,'0'
+bne a0,t0,1f
+la t1,uipage
+sb x0,0(t1) # User entered '0', go to idle screen (page 0)
+1: ret
+
+uidrawcountryselect:
+la a0,uicountryselect
+li a7,4
+ecall
+ret
+
+uihandlecountryselect:
+li a7,132
+ecall # Read one character of input
+li t0,'1'
+bne a0,t0,1f
+la t1,country
+sb x0,0(t1) # User entered '1', change country to DE (0)
+la t1,uipage
+li t2,1
+sb t2,0(t1) # Return to main menu (page 1)
+1: li t0,'2'
+bne a0,t0,1f
+la t1,country
+li t2,1
+sb t2,0(t1) # User entered '2', change country to UK (1)
+la t1,uipage
+li t2,1
+sb t2,0(t1) # Return to main menu (page 1)
+1: li t0,'3'
+bne a0,t0,1f
+la t1,country
+li t2,2
+sb t2,0(t1) # User entered '3', change country to US (2)
+la t1,uipage
+li t2,1
+sb t2,0(t1) # Return to main menu (page 1)
+1: li t0,'0'
+bne a0,t0,1f
+la t1,uipage
+li t2,1
+sb t2,0(t1) # User entered '0', return to main menu (page 1) without changing anything
+1: ret
+
+uidrawadjusttiming:
+la a0,uiadjusttiming
+li a7,4
+ecall
+ret
+
+uihandleadjusttiming:
+li a7,132
+ecall # Read one character of input
+li t0,'1'
+bne a0,t0,1f
+la t1,uipage
+li t2,4
+sb t2,0(t1) # User entered '1', go to gate drop time setting (page 4)
+1: li t0,'2'
+bne a0,t0,1f
+la t1,uipage
+li t2,5
+sb t2,0(t1) # User entered '2', go to initial active time setting (page 5)
+1: li t0,'3'
+bne a0,t0,1f
+la t1,uipage
+li t2,6
+sb t2,0(t1) # User entered '3', go to extension time setting (page 6)
+1: li t0,'0'
+bne a0,t0,1f
+la t1,uipage
+li t2,1
+sb t2,0(t1) # User entered '0', go to main menu (page 1)
+1: ret
+ret
+
+uidrawgatedropdelay:
+la a0,uigatedropdelay
+la t0,gatedroptime
+lbu t0,0(t0) # Load the current setting
+li t1,10
+div t2,t0,t1 # Split it into tens and ones places
+rem t3,t0,t1
+addi t2,t2,0x30 # Convert to ASCII
+addi t3,t3,0x30
+sb t2,27(a0) # Insert the digits into the string
+sb t3,28(a0)
+li a7,4
+ecall # And print it
+ret
+
+uihandlegatedropdelay:
+# Read first digit
+li a7,132
+ecall
+
+# Check if the user wanted to cancel
+li t0,'c'
+bne a0,t0,1f
+la t0,uipage
+li t1,3 # User chose to cancel, go back to timing adjustment (page 3)
+sb t1,0(t0)
+ret
+1:
+
+# Validate and process first digit
+addi s0,a0,-0x30 # Convert the first digit to ASCII
+li t0,10
+bltu s0,t0,1f # Inputs less than 0x30 become negative in the addi above, this branch is unsigned so those become large positive numbers
+la t0,uipage # ^ Thank the RISC-V manual for that trick
+li t1,7
+sb t1,0(t0) # First digit was not valid, go to invalid input error (page 7)
+ret
+1: mul s0,s0,t0 # Multiply the first digit by 10
+
+# Read second digit
+li a7,132
+ecall
+bnez a0,1f
+div s0,s0,t0 # Second digit was null, so the first digit was really the ones place
+li a0,0x30 # Pretend this digit was 0 so validation still passes but the addition doesn't change anything
+1: addi a0,a0,-0x30
+bltu a0,t0,1f # Inputs less than 0x30 become negative in the addi above
+la t0,uipage
+li t1,7
+sb t1,0(t0) # Second digit was not valid, go to invalid input error (page 7)
+ret
+1: add s0,s0,a0 # Sum the two digits together
+bnez s0,1f
+la t0,uipage
+li t1,7
+sb t1,0(t0) # Input was 0, go to invalid input error (page 7)
+ret
+1: la t0,gatedroptime
+sb s0,0(t0) # Write out the new setting
+la t0,uipage
+li t1,3 # Go back to timing adjustment (page 3)
+sb t1,0(t0)
+ret
+
+uidrawinitialtime:
+la a0,uiinitialtime
+la t0,activetime
+lbu t0,0(t0) # Load the current setting
+li t1,10
+div t2,t0,t1 # Split it into tens and ones places
+rem t3,t0,t1
+addi t2,t2,0x30 # Convert to ASCII
+addi t3,t3,0x30
+sb t2,29(a0) # Insert the digits into the string
+sb t3,30(a0)
+li a7,4
+ecall # And print it
+ret
+
+uihandleinitialtime:
+# Read first digit
+li a7,132
+ecall
+
+# Check if the user wanted to cancel
+li t0,'c'
+bne a0,t0,1f
+la t0,uipage
+li t1,3 # User chose to cancel, go back to timing adjustment (page 3)
+sb t1,0(t0)
+ret
+1:
+
+# Validate and process first digit
+addi s0,a0,-0x30 # Convert the first digit to ASCII
+li t0,10
+bltu s0,t0,1f # Inputs less than 0x30 become negative in the addi above, this branch is unsigned so those become large positive numbers
+la t0,uipage # ^ Thank the RISC-V manual for that trick
+li t1,7
+sb t1,0(t0) # First digit was not valid, go to invalid input error (page 7)
+ret
+1: mul s0,s0,t0 # Multiply the first digit by 10
+
+# Read second digit
+li a7,132
+ecall
+bnez a0,1f
+div s0,s0,t0 # Second digit was null, so the first digit was really the ones place
+li a0,0x30 # Pretend this digit was 0 so validation still passes but the addition doesn't change anything
+1: addi a0,a0,-0x30
+bltu a0,t0,1f # Inputs less than 0x30 become negative in the addi above
+la t0,uipage
+li t1,7
+sb t1,0(t0) # Second digit was not valid, go to invalid input error (page 7)
+ret
+1: add s0,s0,a0 # Sum the two digits together
+bnez s0,1f
+la t0,uipage
+li t1,7
+sb t1,0(t0) # Input was 0, go to invalid input error (page 7)
+ret
+1: la t0,activetime
+sb s0,0(t0) # Write out the new setting
+la t0,uipage
+li t1,3 # Go back to timing adjustment (page 3)
+sb t1,0(t0)
+ret
+
+uidrawextensiontime:
+la a0,uiextensiontime
+la t0,extensiontime
+lbu t0,0(t0) # Load the current setting
+li t1,10
+div t2,t0,t1 # Split it into tens and ones places
+rem t3,t0,t1
+addi t2,t2,0x30 # Convert to ASCII
+addi t3,t3,0x30
+sb t2,26(a0) # Insert the digits into the string
+sb t3,27(a0)
+li a7,4
+ecall # And print it
+ret
+
+uihandleextensiontime:
+# Read first digit
+li a7,132
+ecall
+
+# Check if the user wanted to cancel
+li t0,'c'
+bne a0,t0,1f
+la t0,uipage
+li t1,3 # User chose to cancel, go back to timing adjustment (page 3)
+sb t1,0(t0)
+ret
+1:
+
+# Validate and process first digit
+addi s0,a0,-0x30 # Convert the first digit to ASCII
+li t0,10
+bltu s0,t0,1f # Inputs less than 0x30 become negative in the addi above, this branch is unsigned so those become large positive numbers
+la t0,uipage # ^ Thank the RISC-V manual for that trick
+li t1,7
+sb t1,0(t0) # First digit was not valid, go to invalid input error (page 7)
+ret
+1: mul s0,s0,t0 # Multiply the first digit by 10
+
+# Read second digit
+li a7,132
+ecall
+bnez a0,1f
+div s0,s0,t0 # Second digit was null, so the first digit was really the ones place
+li a0,0x30 # Pretend this digit was 0 so validation still passes but the addition doesn't change anything
+1: addi a0,a0,-0x30
+bltu a0,t0,1f # Inputs less than 0x30 become negative in the addi above
+la t0,uipage
+li t1,7
+sb t1,0(t0) # Second digit was not valid, go to invalid input error (page 7)
+ret
+1: add s0,s0,a0 # Sum the two digits together
+bnez s0,1f
+la t0,uipage
+li t1,7
+sb t1,0(t0) # Input was 0, go to invalid input error (page 7)
+ret
+1: la t0,extensiontime
+sb s0,0(t0) # Write out the new setting
+la t0,uipage
+li t1,3 # Go back to timing adjustment (page 3)
+sb t1,0(t0)
+ret
+
+uidrawinvalidinput:
+la a0,uiinvalidinput
+li a7,4
+ecall
+ret
+
+uihandleinvalidinput:
+la t0,uipage
+li t1,3 # Go back to timing adjustment (page 3)
+sb t1,0(t0)
+ret
+
+uidrawunknown:
+la a0,uiunknown
+li a7,4
+ecall
+ret
+
+uipage: .byte 0
+uiidle: .asciz "\nRailroad Crossing 2\nfor RVController\nMode: ??\n\nPress 'm' for menu\n'a' to activate now"
+uiactive: .asciz "\nRailroad Crossing 2\nfor RVController\nMode: ??\nCrossing is active\n\nPress 'm' for menu"
+uimainmenu: .asciz "\nMAIN MENU\n1: Change Country\n2: Adjust Timing\n\n\n0: Exit"
+uiunknown: .asciz "\nInternal error\n\nUnknown UI page\n\n\n"
+uicountryselect: .asciz "\nCHANGE COUNTRY\n1: Germany\n2: United Kingdom\n3: United States\n\n0: Cancel"
+uiadjusttiming: .asciz "\nADJUST TIMING\n1: Gate Drop Delay\n2: Init. Active Time\n3: Extension Time\n\n0: Cancel"
+uigatedropdelay: .asciz "\nGATE DROP DELAY\n\nCurrent: XX sec\n\nEnter new time or\n'c' to cancel:"
+uiinitialtime: .asciz "\nINIT. ACTIVE TIME\n\nCurrent: XX sec\n\nEnter new time or\n'c' to cancel:"
+uiextensiontime: .asciz "\nEXTENSION TIME\n\nCurrent: XX sec\n\nEnter new time or\n'c' to cancel:"
+uiinvalidinput: .asciz "\nInvalid entry\n\nPress any key\n\n\n"
+uide: .asciz "DE"
+uiuk: .asciz "UK"
+uius: .asciz "US"