#############################################################
#
# UART Test Demo Program  -  Print message, get input, and loop.
#
# Exercise the memory-mapped UART0 device. It uses no other functions or code.
#
# 14 December 2023  -- Harry Porter III
#
# This program can be assembled as with:
#     asm testUART.s -o testUART.o
#     link testUART.o -o testUART.exe -k
# It can be run with:
#     blitz testUART.exe -raw -g
# It can also be downloaded and run on the MicroBlitz FPGA.
#
# Uses the standard calling conventions. Runs with interrupts disabled.
#
#############################################################

	.begin		kernel, startaddr=0x0_0000_0008, gp=undefined
	.sourcefile	"testUART.s", "Stand-alone demo assembly program"

	.function	"main",line=0,framesize=0
_entry:
	.export		_entry
	movi		sp,stackTop		# Initialize stack
	movi		r1,msg1			# Print greeting
	call		PrintString		# .
InfiniteLoop:					# LOOP FOREVER
	movi		r1,msg2			#   Print "Enter characters: "
	call		PrintString		#   .
Loop:						#   LOOP
	call		ReadChar		#     Read a byte into r1
	beqi		r1,'q',Loop_Exit	#     If 'q' then break
	call		PrintChar		#     Print it
	jump		Loop			#   ENDLOOP
Loop_Exit:					#   .
	call		PrintChar		#   Echo the 'q'
	movi		r1,msg3			#   Print "About to debug"
	call		PrintString		#   .
	debug					#   Halt execution
	jump		InfiniteLoop		# ENDLOOP
	.endfunction

msg1:		.string		"\r\n**********  UART TEST PROGRAM RUNNING  **********\r\nUse Control-C to exit.\r\n\0"
msg2:		.string		"Type some characters (type \'q\' to exit): \0"
msg3:		.string		"\r\n**********  About to execute the DEBUG instruction. Have a look"
		.string		   " at regs, etc. Type \'g\' to resume.  **********\r\n\0"

		.align		8



#############################################################
#
# Area for the stack
#
#############################################################

stackLen:	.equ		100 * 8
stack:		.skip		stackLen
stackTop:	.equ		stack+stackLen



#############################################################
#
# Fixed addresses related to the UART memory-mapped I/O device
#
#############################################################

UART0_DEVICE_START_ADDR:	.equ	0x4_0020_4000
UART0_DEVICE_SEND_BYTE_ADDR:	.equ	UART0_DEVICE_START_ADDR + 0	# size 8 bytes, write-only
UART0_DEVICE_RECV_BYTE_ADDR:	.equ	UART0_DEVICE_START_ADDR + 0	# size 8 bytes, read-only
UART0_DEVICE_STATUS_ADDR:	.equ	UART0_DEVICE_START_ADDR + 8	# size 8 bytes, read-only
UART0_DEVICE_SETUP_ADDR:	.equ	UART0_DEVICE_START_ADDR + 8	# size 8 bytes, write-only

UART0_RECV_READY_BIT:		.equ	0x0000_0000_0000_0001		# 0=waiting to receive; 1=char available
UART0_SEND_READY_BIT:		.equ	0x0000_0000_0000_0002		# 0=busy sending; 1=ready for next output



#############################################################
#
# ReadChar () returns byte
#
# Fetch a byte from the input, from the memory-mapped UART device.
# The byte is not echoed and may be part of a multi-byte UTF-8 character.
#
# Passed: < nothing >
# Returns: r1 = the character (-127...128)
#
#############################################################

ReadChar:
	.function	"ReadChar",line=0,framesize=0
	loadd		r1,UART0_DEVICE_STATUS_ADDR
	andi		r1,r1,UART0_RECV_READY_BIT
	beqz		r1,ReadChar
	loadd		r1,UART0_DEVICE_RECV_BYTE_ADDR
	ret
	.endfunction


#############################################################
#
# PrintChar (byte)
#
# Send a byte to the output.
#
# Passed: r1 = character
#
#############################################################

PrintChar:
	.function	"PrintChar",line=0,framesize=0
	loadd		r2,UART0_DEVICE_STATUS_ADDR
	andi		r2,r2,UART0_SEND_READY_BIT
	beqz		r2,PrintChar
	stored		UART0_DEVICE_SEND_BYTE_ADDR,r1
	ret
	.endfunction


#############################################################
#
# PrintString (buffer: ptr to byte)
#
# Passed: r1 = ptr to NUL terminated string
#
#############################################################

PrintString:
	.function	"PrintString",line=0,framesize=16
	enterfun	sp,sp,-16
	stored		0(sp),r1
PS_Loop:
	loadd		r2,0(sp)
	loadb		r1,0(r2)
	addi		r2,r2,1
	stored		0(sp),r2
	beqz		r1,PS_Exit
	call		PrintChar
	jump		PS_Loop
PS_Exit:
	exitfun		sp,sp,+16
	.endfunction



