diff options
Diffstat (limited to 'assembly/rrxing2/ui.S')
| -rw-r--r-- | assembly/rrxing2/ui.S | 452 |
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" |
