Ein Monitorprogramm für mein Yuki SoC.
Der Monitor wird an dem seriellen Port SIO 0 mit 115200 Baud bereitgestellt und ist mithilfe des Yuki CPU assembler entwickelt worden. Er kann benutzt werden um den Speicher auszulesen, zu bearbeiten, um and Speicherstellen zu springen und Unterprogramme aufzurufen. Alle Daten werden als Hexadezimalzahlen dargestellt.
Funktionen:
- Einzelwerte schreiben
- Kontinuirlich Werte in aufeinanderfolgende Speicherzellen schreiben
- Einzelwerte auslesen
- Kontinuirlich Werte aus aufeinanderfolgenden Speicherzellen lesen
- An Adressen springen
- Unterprogramme aufrufen
Der Quellcode des Monitors
# Title: Yuki Monitor for Yuki Soc
# Author: R.Lux
# Last edited: 06.01.2018
.org 0x000000
.glbl DEBUG_ADDRESS 0xFFCD55
.glbl SIO0_OUT 0xFFCFEF
.glbl SIO0_BAUD 0xFFCFE1
.glbl SIO0_INT_MODE 0xFFCFE2
.glbl SIO0_INT_THRESHOLD 0xFFCFE0
.glbl SIO0_RX_DATA? 0xFFCFE3
.glbl SIO0_TX_READY? 0xFFCFE4
.glbl FUNCTIONSPACE0 0x000FF0
.glbl FUNCTIONSPACE1 0x000FF1
.glbl FUNCTIONSPACE2 0x000FF2
.glbl FUNCTIONSPACE3 0x000FF3
.glbl FUNCTIONSPACE4 0x000FF4
.glbl FUNCTIONSPACE5 0x000FF5
.glbl FUNCTIONSPACE6 0x000FF6
.glbl FUNCTIONSPACE7 0x000FF7
.glbl FUNCTIONSPACE8 0x000FF8
# Jump to the monitor start
JMP MONITOR_START
NOP
# Functions...
.glbl F_OUTPUT_STRINGZ
NOP
# ===== Output a zero-terminated string (start address in X) on SIO0 =====
# Save working registers..
PUSH R0
NOP
# Start address of zero-terminated string is in the X register
.lbl F_OUTPUT_STRINGZLOOP
LD R0 (X)
INC X
TST R0 0x00
JZ F_OUTPUT_STRINGZEND
NOP
# Output char
CALL F_OUTPUT_R0
# Repeat until 0x00 terminator
JMP F_OUTPUT_STRINGZLOOP
.lbl F_OUTPUT_STRINGZEND
# Restore working registers
POP R0
# Return to function caller
RET
NOP
.glbl F_OUTPUT_R0
# ==== Output R0 on SIO0 ======
PUSH R1
.lbl F_OUTPUT_R0_WAIT
LD R1 (SIO0_TX_READY?)
TST R1 0x00
JZ F_OUTPUT_R0_WAIT
ST R0 (SIO0_OUT)
POP R1
# Return to caller
RET
NOP
.glbl F_INPUT_R0
# ==== Get 1 byte from SIO0 and store it in R0
.lbl F_INPUT_R0_WAIT
LD R0 (SIO0_RX_DATA?)
TST R0 0x00
JZ F_INPUT_R0_WAIT
LD R0 (SIO0_OUT)
# Return to caller
RET
NOP
.glbl F_INPUT_UNTIL_\n
# ==== Start address in X, generate a zero-terminated string using the data of SIO0 until \n is input ====
# Last \n is not saved
# Save working registers
PUSH X
PUSH R0
PUSH R1
.lbl F_INPUT_UNTIL_\n_WAIT
LD R1 (SIO0_RX_DATA?)
TST R1 0x00
JZ F_INPUT_UNTIL_\n_WAIT
# We have a new char
LD R0 (SIO0_OUT)
# Delete last char
TST R0 0x08
JE F_INPUT_UNTIL_\n_DEL
JMP END_F_INPUT_UNTIL_\n_DEL
.lbl F_INPUT_UNTIL_\n_DEL
DEC X
LD R0 0x00
ST R0 (X)
LD R0 0x08
CALL F_OUTPUT_R0
JMP F_INPUT_UNTIL_\n_WAIT
.lbl END_F_INPUT_UNTIL_\n_DEL
TST R0 0x0A
JE F_INPUT_UNTIL_\n_FINISHED
CALL F_OUTPUT_R0
ST R0 (X)
INC X
JMP F_INPUT_UNTIL_\n_WAIT
.lbl F_INPUT_UNTIL_\n_FINISHED
# Save tailing 0
LD R0 0x00
ST R0 (X)
# Restore working registers
POP R1
POP R0
POP X
# Return to caller
RET
NOP
# Leave space for ISRs
.space 0xA0
.glbl MONITOR_START
# Initialise SIO0
LD R0 0d7# 115200 Baud
ST R0 (SIO0_BAUD)
LD R0 0d0# Interrupts disabled
ST R0 (SIO0_INT_MODE)
LD R0 0d1# Recognise all data even if it is only 1 byte
ST R0 (SIO0_INT_THRESHOLD)
# Allocate 256 bytes total for the stacks
LD USP 0x000F00
LD SSP 0x000F7F
# Output startup message
LD X hello_msg
CALL F_OUTPUT_STRINGZ
LD R0 0x55
ST R0 (DEBUG_ADDRESS)
.lbl MAINLOOP
LD R0 0x3E
CALL F_OUTPUT_R0
LD X 0x000FD0
CALL F_INPUT_UNTIL_\n
LD R1 (0x000FD0)
TST R1 0x72# Command: r (Read data from address)
JE r_CMD
JMP END_r_CMD
.glbl r_CMD
# syntax:r AAAAAA
# returns: byte at AAAAAA
LD R0 0x0A
CALL F_OUTPUT_R0
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
LD X (FUNCTIONSPACE3)
LD R0 (X)
PUSH R0
LD R0 0x00
ST R0 (0x000FD8)
LD X 0x000FD2
CALL F_OUTPUT_STRINGZ
LD R0 0x3A
CALL F_OUTPUT_R0
POP R0
CALL F_OUTPUT_R0_ASCII
LD R0 0x0A
CALL F_OUTPUT_R0
JMP MAINLOOP
.lbl END_r_CMD
TST R1 0x77# Command: w (Write data to address)
JE w_CMD
JMP END_w_CMD
.glbl w_CMD
# syntax:w AAAAAA BB
# returns: -
LD R0 0x0A
CALL F_OUTPUT_R0
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
LD X (FUNCTIONSPACE3)
PUSH X
LD X 0x000FD9
CALL F_CONVERT_ASCII_R0
POP X
ST R0 (X)
CALL F_OUTPUT_R0_ASCII
LD R0 0x0A
CALL F_OUTPUT_R0
JMP MAINLOOP
.lbl END_w_CMD
TST R1 0x52# Command: R (Read data between addresses)
JE R_CMD
JMP END_R_CMD
.glbl R_CMD
# syntax:R AAAAAA BBBBBB
# display all bytes between AAAAAA and BBBBBB
LD R0 0x0A
CALL F_OUTPUT_R0
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
# Mask off lower nibble of start address
LD Y (FUNCTIONSPACE3)
LD X 0x000FD9
CALL F_INPUT_PTR_ASCII
# Use R2 as rowcounter
LD R2 0x00
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
.lbl R_CMD_LOOP
LD R0 (Y)
# Output data
CALL F_OUTPUT_R0_ASCII
# Seperate data by spaces
LD R0 0x20
CALL F_OUTPUT_R0
INC Y
# Loop until all bytes are output
JE Y (FUNCTIONSPACE3) R_CMD_LOOP_END
ADD R2 0x01
AND R2 0b00001111
TST R2 0x00
JE R_CMD_NEWLINE
JMP END_R_CMD_NEWLINE
.lbl R_CMD_NEWLINE
LD R0 0x0A
CALL F_OUTPUT_R0
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
NOP
.lbl END_R_CMD_NEWLINE
# Loop until all bytes are output
JE Y (FUNCTIONSPACE3) R_CMD_LOOP_END
NOP
JMP R_CMD_LOOP
.lbl R_CMD_LOOP_END
TST R2 0x0F
JE R_CMD_NEWLINE_SEC
JMP END_R_CMD_NEWLINE_SEC
.lbl R_CMD_NEWLINE_SEC
LD R0 0x0A
CALL F_OUTPUT_R0
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
NOP
.lbl END_R_CMD_NEWLINE_SEC
LD R0 (Y)
CALL F_OUTPUT_R0_ASCII
LD R0 0x0A
CALL F_OUTPUT_R0
JMP MAINLOOP
.lbl END_R_CMD
TST R1 0x57# Command: W(write multiple bytes)
JE W_CMD
JMP END_W_CMD_1
.lbl W_CMD
# syntax:
#W SSSSSS - start writing bytes at SSSSSS
# only send data after .
# send q to stop
# Use R3 as rowcounter
LD R3 0x00
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
LD Y (FUNCTIONSPACE3)
LD R0 0x0A
CALL F_OUTPUT_R0
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
LD R0 0x2E
CALL F_OUTPUT_R0
.lbl W_CMD_LOOP
CALL F_INPUT_ASCII_R0
LD R2 (0x000FD0)
TST R2 0x71
JE END_W_CMD_0
LD R2 (0x000FD1)
TST R2 0x71
JE END_W_CMD_0
NOP
ST R0 (Y)
INC Y
ADD R3 0x01
AND R3 0b00001111
TST R3 0x00
JE W_CMD_NEWLINE
JMP END_W_CMD_NEWLINE
.lbl W_CMD_NEWLINE
LD R0 0x0A
CALL F_OUTPUT_R0
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
NOP
.lbl END_W_CMD_NEWLINE
NOP
LD R0 0x7F
CALL F_OUTPUT_R0
LD R0 0x2E
CALL F_OUTPUT_R0
JMP W_CMD_LOOP
.lbl END_W_CMD_0
NOP
LD R0 0x0A
CALL F_OUTPUT_R0
JMP MAINLOOP
.lbl END_W_CMD_1
TST R1 0x67# Command: g (Jump to address)
JE g_CMD
JMP END_g_CMD
.glbl g_CMD
# Get address
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
# Jump to address
JMP (FUNCTIONSPACE3)
.lbl END_g_CMD
TST R1 0x63# Command: c (Call function)
JE c_CMD
JMP END_c_CMD
.glbl c_CMD
# Get address
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
# Jump to address
CALL (FUNCTIONSPACE3)
LD R0 0x0A
CALL F_OUTPUT_R0
.lbl END_c_CMD
TST R1 0x62# Command: b (enter binary mode)
JE b_CMD
JMP END_b_CMD
.glbl b_CMD
# This mode is useful for uploading and downloading larger data chunks
# R1 holds the command
# 0x00 response means sucess
# 0x55 response means ready
# 0xFF response means failure
CALL F_INPUT_R0
PUSH R0
POP R1
TST R1 0x01# test if binary mode is ready
JE b_CMD_ping
JMP END_b_CMD_ping
.lbl b_CMD_ping
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_ping
TST R1 0x02# read a single value
JE b_CMD_sread
JMP END_b_CMD_sread
.lbl b_CMD_sread
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
LD X (FUNCTIONSPACE0)
LD R0 (X)
CALL F_OUTPUT_R0
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_sread
TST R1 0x03# write a single value
JE b_CMD_swrite
JMP END_b_CMD_swrite
.lbl b_CMD_swrite
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
CALL F_INPUT_R0
ST R0 ((FUNCTIONSPACE0))
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_swrite
TST R1 0x04# read multiple values
JE b_CMD_mread
JMP END_b_CMD_mread
.lbl b_CMD_mread
# Get start address of Y
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
LD Y (FUNCTIONSPACE0)
# Get end address
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
NOP
.lbl b_CMD_mread_loop
LD R0 (Y)
CALL F_OUTPUT_R0
JE Y (FUNCTIONSPACE0) b_CMD_mread_loop_end
INC Y
JMP b_CMD_mread_loop
.lbl b_CMD_mread_loop_end
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_mread
TST R1 0x05# write multiple values
JE b_CMD_mwrite
JMP END_b_CMD_mwrite
.lbl b_CMD_mwrite
# Get start address of Y
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
LD Y (FUNCTIONSPACE0)
# Get end address
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE3)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE4)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE5)
NOP
.lbl b_CMD_mwrite_loop
CALL F_INPUT_R0
ST R0 (Y)
JE Y (FUNCTIONSPACE3) b_CMD_mwrite_loop_end
# Indicate being ready
LD R0 0x55
CALL F_OUTPUT_R0
INC Y
JMP b_CMD_mwrite_loop
.lbl b_CMD_mwrite_loop_end
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_mwrite
TST R1 0x06# exit binary mode
JE b_CMD_exit
JMP END_b_CMD_exit
.lbl b_CMD_exit
LD R0 0x00
CALL F_OUTPUT_R0
JMP END_b_CMD
.lbl END_b_CMD_exit
JMP b_CMD
.lbl END_b_CMD
JMP MAINLOOP
HALT
LD R0 0x00
ADD R0 0x01
JMP- 2L
# Data section
.glbl hello_msg
.strz "Yuki Monitor V1.0\n"
# Include file section
.inc ascii_functions.s
# Save all global labels
.exp_lbl yuki_labels.lbl
# Author: R.Lux
# Last edited: 06.01.2018
.org 0x000000
.glbl DEBUG_ADDRESS 0xFFCD55
.glbl SIO0_OUT 0xFFCFEF
.glbl SIO0_BAUD 0xFFCFE1
.glbl SIO0_INT_MODE 0xFFCFE2
.glbl SIO0_INT_THRESHOLD 0xFFCFE0
.glbl SIO0_RX_DATA? 0xFFCFE3
.glbl SIO0_TX_READY? 0xFFCFE4
.glbl FUNCTIONSPACE0 0x000FF0
.glbl FUNCTIONSPACE1 0x000FF1
.glbl FUNCTIONSPACE2 0x000FF2
.glbl FUNCTIONSPACE3 0x000FF3
.glbl FUNCTIONSPACE4 0x000FF4
.glbl FUNCTIONSPACE5 0x000FF5
.glbl FUNCTIONSPACE6 0x000FF6
.glbl FUNCTIONSPACE7 0x000FF7
.glbl FUNCTIONSPACE8 0x000FF8
# Jump to the monitor start
JMP MONITOR_START
NOP
# Functions...
.glbl F_OUTPUT_STRINGZ
NOP
# ===== Output a zero-terminated string (start address in X) on SIO0 =====
# Save working registers..
PUSH R0
NOP
# Start address of zero-terminated string is in the X register
.lbl F_OUTPUT_STRINGZLOOP
LD R0 (X)
INC X
TST R0 0x00
JZ F_OUTPUT_STRINGZEND
NOP
# Output char
CALL F_OUTPUT_R0
# Repeat until 0x00 terminator
JMP F_OUTPUT_STRINGZLOOP
.lbl F_OUTPUT_STRINGZEND
# Restore working registers
POP R0
# Return to function caller
RET
NOP
.glbl F_OUTPUT_R0
# ==== Output R0 on SIO0 ======
PUSH R1
.lbl F_OUTPUT_R0_WAIT
LD R1 (SIO0_TX_READY?)
TST R1 0x00
JZ F_OUTPUT_R0_WAIT
ST R0 (SIO0_OUT)
POP R1
# Return to caller
RET
NOP
.glbl F_INPUT_R0
# ==== Get 1 byte from SIO0 and store it in R0
.lbl F_INPUT_R0_WAIT
LD R0 (SIO0_RX_DATA?)
TST R0 0x00
JZ F_INPUT_R0_WAIT
LD R0 (SIO0_OUT)
# Return to caller
RET
NOP
.glbl F_INPUT_UNTIL_\n
# ==== Start address in X, generate a zero-terminated string using the data of SIO0 until \n is input ====
# Last \n is not saved
# Save working registers
PUSH X
PUSH R0
PUSH R1
.lbl F_INPUT_UNTIL_\n_WAIT
LD R1 (SIO0_RX_DATA?)
TST R1 0x00
JZ F_INPUT_UNTIL_\n_WAIT
# We have a new char
LD R0 (SIO0_OUT)
# Delete last char
TST R0 0x08
JE F_INPUT_UNTIL_\n_DEL
JMP END_F_INPUT_UNTIL_\n_DEL
.lbl F_INPUT_UNTIL_\n_DEL
DEC X
LD R0 0x00
ST R0 (X)
LD R0 0x08
CALL F_OUTPUT_R0
JMP F_INPUT_UNTIL_\n_WAIT
.lbl END_F_INPUT_UNTIL_\n_DEL
TST R0 0x0A
JE F_INPUT_UNTIL_\n_FINISHED
CALL F_OUTPUT_R0
ST R0 (X)
INC X
JMP F_INPUT_UNTIL_\n_WAIT
.lbl F_INPUT_UNTIL_\n_FINISHED
# Save tailing 0
LD R0 0x00
ST R0 (X)
# Restore working registers
POP R1
POP R0
POP X
# Return to caller
RET
NOP
# Leave space for ISRs
.space 0xA0
.glbl MONITOR_START
# Initialise SIO0
LD R0 0d7# 115200 Baud
ST R0 (SIO0_BAUD)
LD R0 0d0# Interrupts disabled
ST R0 (SIO0_INT_MODE)
LD R0 0d1# Recognise all data even if it is only 1 byte
ST R0 (SIO0_INT_THRESHOLD)
# Allocate 256 bytes total for the stacks
LD USP 0x000F00
LD SSP 0x000F7F
# Output startup message
LD X hello_msg
CALL F_OUTPUT_STRINGZ
LD R0 0x55
ST R0 (DEBUG_ADDRESS)
.lbl MAINLOOP
LD R0 0x3E
CALL F_OUTPUT_R0
LD X 0x000FD0
CALL F_INPUT_UNTIL_\n
LD R1 (0x000FD0)
TST R1 0x72# Command: r (Read data from address)
JE r_CMD
JMP END_r_CMD
.glbl r_CMD
# syntax:r AAAAAA
# returns: byte at AAAAAA
LD R0 0x0A
CALL F_OUTPUT_R0
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
LD X (FUNCTIONSPACE3)
LD R0 (X)
PUSH R0
LD R0 0x00
ST R0 (0x000FD8)
LD X 0x000FD2
CALL F_OUTPUT_STRINGZ
LD R0 0x3A
CALL F_OUTPUT_R0
POP R0
CALL F_OUTPUT_R0_ASCII
LD R0 0x0A
CALL F_OUTPUT_R0
JMP MAINLOOP
.lbl END_r_CMD
TST R1 0x77# Command: w (Write data to address)
JE w_CMD
JMP END_w_CMD
.glbl w_CMD
# syntax:w AAAAAA BB
# returns: -
LD R0 0x0A
CALL F_OUTPUT_R0
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
LD X (FUNCTIONSPACE3)
PUSH X
LD X 0x000FD9
CALL F_CONVERT_ASCII_R0
POP X
ST R0 (X)
CALL F_OUTPUT_R0_ASCII
LD R0 0x0A
CALL F_OUTPUT_R0
JMP MAINLOOP
.lbl END_w_CMD
TST R1 0x52# Command: R (Read data between addresses)
JE R_CMD
JMP END_R_CMD
.glbl R_CMD
# syntax:R AAAAAA BBBBBB
# display all bytes between AAAAAA and BBBBBB
LD R0 0x0A
CALL F_OUTPUT_R0
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
# Mask off lower nibble of start address
LD Y (FUNCTIONSPACE3)
LD X 0x000FD9
CALL F_INPUT_PTR_ASCII
# Use R2 as rowcounter
LD R2 0x00
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
.lbl R_CMD_LOOP
LD R0 (Y)
# Output data
CALL F_OUTPUT_R0_ASCII
# Seperate data by spaces
LD R0 0x20
CALL F_OUTPUT_R0
INC Y
# Loop until all bytes are output
JE Y (FUNCTIONSPACE3) R_CMD_LOOP_END
ADD R2 0x01
AND R2 0b00001111
TST R2 0x00
JE R_CMD_NEWLINE
JMP END_R_CMD_NEWLINE
.lbl R_CMD_NEWLINE
LD R0 0x0A
CALL F_OUTPUT_R0
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
NOP
.lbl END_R_CMD_NEWLINE
# Loop until all bytes are output
JE Y (FUNCTIONSPACE3) R_CMD_LOOP_END
NOP
JMP R_CMD_LOOP
.lbl R_CMD_LOOP_END
TST R2 0x0F
JE R_CMD_NEWLINE_SEC
JMP END_R_CMD_NEWLINE_SEC
.lbl R_CMD_NEWLINE_SEC
LD R0 0x0A
CALL F_OUTPUT_R0
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
NOP
.lbl END_R_CMD_NEWLINE_SEC
LD R0 (Y)
CALL F_OUTPUT_R0_ASCII
LD R0 0x0A
CALL F_OUTPUT_R0
JMP MAINLOOP
.lbl END_R_CMD
TST R1 0x57# Command: W(write multiple bytes)
JE W_CMD
JMP END_W_CMD_1
.lbl W_CMD
# syntax:
#W SSSSSS - start writing bytes at SSSSSS
# only send data after .
# send q to stop
# Use R3 as rowcounter
LD R3 0x00
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
LD Y (FUNCTIONSPACE3)
LD R0 0x0A
CALL F_OUTPUT_R0
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
LD R0 0x2E
CALL F_OUTPUT_R0
.lbl W_CMD_LOOP
CALL F_INPUT_ASCII_R0
LD R2 (0x000FD0)
TST R2 0x71
JE END_W_CMD_0
LD R2 (0x000FD1)
TST R2 0x71
JE END_W_CMD_0
NOP
ST R0 (Y)
INC Y
ADD R3 0x01
AND R3 0b00001111
TST R3 0x00
JE W_CMD_NEWLINE
JMP END_W_CMD_NEWLINE
.lbl W_CMD_NEWLINE
LD R0 0x0A
CALL F_OUTPUT_R0
CALL F_OUTPUT_Y_ASCII
LD R0 0x3A
CALL F_OUTPUT_R0
NOP
.lbl END_W_CMD_NEWLINE
NOP
LD R0 0x7F
CALL F_OUTPUT_R0
LD R0 0x2E
CALL F_OUTPUT_R0
JMP W_CMD_LOOP
.lbl END_W_CMD_0
NOP
LD R0 0x0A
CALL F_OUTPUT_R0
JMP MAINLOOP
.lbl END_W_CMD_1
TST R1 0x67# Command: g (Jump to address)
JE g_CMD
JMP END_g_CMD
.glbl g_CMD
# Get address
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
# Jump to address
JMP (FUNCTIONSPACE3)
.lbl END_g_CMD
TST R1 0x63# Command: c (Call function)
JE c_CMD
JMP END_c_CMD
.glbl c_CMD
# Get address
LD X 0x000FD2
CALL F_INPUT_PTR_ASCII
# Jump to address
CALL (FUNCTIONSPACE3)
LD R0 0x0A
CALL F_OUTPUT_R0
.lbl END_c_CMD
TST R1 0x62# Command: b (enter binary mode)
JE b_CMD
JMP END_b_CMD
.glbl b_CMD
# This mode is useful for uploading and downloading larger data chunks
# R1 holds the command
# 0x00 response means sucess
# 0x55 response means ready
# 0xFF response means failure
CALL F_INPUT_R0
PUSH R0
POP R1
TST R1 0x01# test if binary mode is ready
JE b_CMD_ping
JMP END_b_CMD_ping
.lbl b_CMD_ping
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_ping
TST R1 0x02# read a single value
JE b_CMD_sread
JMP END_b_CMD_sread
.lbl b_CMD_sread
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
LD X (FUNCTIONSPACE0)
LD R0 (X)
CALL F_OUTPUT_R0
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_sread
TST R1 0x03# write a single value
JE b_CMD_swrite
JMP END_b_CMD_swrite
.lbl b_CMD_swrite
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
CALL F_INPUT_R0
ST R0 ((FUNCTIONSPACE0))
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_swrite
TST R1 0x04# read multiple values
JE b_CMD_mread
JMP END_b_CMD_mread
.lbl b_CMD_mread
# Get start address of Y
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
LD Y (FUNCTIONSPACE0)
# Get end address
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
NOP
.lbl b_CMD_mread_loop
LD R0 (Y)
CALL F_OUTPUT_R0
JE Y (FUNCTIONSPACE0) b_CMD_mread_loop_end
INC Y
JMP b_CMD_mread_loop
.lbl b_CMD_mread_loop_end
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_mread
TST R1 0x05# write multiple values
JE b_CMD_mwrite
JMP END_b_CMD_mwrite
.lbl b_CMD_mwrite
# Get start address of Y
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE0)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE1)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE2)
LD Y (FUNCTIONSPACE0)
# Get end address
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE3)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE4)
CALL F_INPUT_R0
ST R0 (FUNCTIONSPACE5)
NOP
.lbl b_CMD_mwrite_loop
CALL F_INPUT_R0
ST R0 (Y)
JE Y (FUNCTIONSPACE3) b_CMD_mwrite_loop_end
# Indicate being ready
LD R0 0x55
CALL F_OUTPUT_R0
INC Y
JMP b_CMD_mwrite_loop
.lbl b_CMD_mwrite_loop_end
LD R0 0x00
CALL F_OUTPUT_R0
JMP b_CMD
.lbl END_b_CMD_mwrite
TST R1 0x06# exit binary mode
JE b_CMD_exit
JMP END_b_CMD_exit
.lbl b_CMD_exit
LD R0 0x00
CALL F_OUTPUT_R0
JMP END_b_CMD
.lbl END_b_CMD_exit
JMP b_CMD
.lbl END_b_CMD
JMP MAINLOOP
HALT
LD R0 0x00
ADD R0 0x01
JMP- 2L
# Data section
.glbl hello_msg
.strz "Yuki Monitor V1.0\n"
# Include file section
.inc ascii_functions.s
# Save all global labels
.exp_lbl yuki_labels.lbl