* serial.asm


SC0BDH	equ	$00C0	; SCI baud rate control registers
SC0BDL	equ	$00C1	;

SC0CR1	equ	$00C2	; SCI Control Register 1
SC0CR2	equ	$00C3	; SCI Control Register 2
SC0SR1	equ	$00C4	; SCI Status Register 1
SC0SR2	equ	$00C5	; SCI Status Register 2
SC0DRH	equ	$00C6	; SCI Data Register High
SC0DRL	equ	$00C7	; SCI Data Register Low

; ---------- subroutines ------------


***
;tc_check: "serial.asm"
;	Used to make sure that the transfer is complete before another character is sent.
;	Reg Input:
;		None
;	Reg Output:
;		None
***

					; polling subroutine to make sure system
tc_check:				; is ready before transferring another character
	psha				; saves the state of a, which will be modified
tc_2:	
     	ldaa	SC0SR1			; checks the transfer complete status bit in the
	anda	#%01000000		; status register by anding it with the proper bit
	beq	tc_2			; keeps polling if transfer is not complete
	pula				; restores state of a
	rts				; returns

***
;init_serial_tx: "serial.asm"
;	Turns on only the serial transmit system at 9600 baud.
;	Reg Input:
;		None
;	Reg Output:
;		None
***



init_serial_tx:

	ldaa 	#%00000000
	staa	SC0CR1

	ldaa	#%00001000		; receiver. it does this by specifying exactly
	staa	SC0CR2			; what is on in the serial control register 2

*					; set 9600 baud
	ldaa	#$00			; the top register should be 0
	staa	SC0BDH			; so we load it with zero


#ifdef _8MHZ_
	ldaa	#$1a			; this sets 9600 for a 8MHZ HC12
#endif

#ifdef _4MHZ_
	ldaa	#13			; this sets 9600 for a 4MHZ HC12
#endif

#ifdef _4800_
	lsla				; this sets 4800 as the baud rate, by doubling the divider
#endif


	staa	SC0BDL			; baud rate is loaded and will take effect now
*					; this turns on the transmitter AND turns off the
	rts				; returns


***
;init_serial_tx_rx: "serial.asm"
;	Turns on both the serial transmitter and receiver at 9600 baud.
;	Reg Input:
;		None
;	Reg Output:
;		None
***

init_serial_tx_rx:

	ldaa 	#%00000000
	staa	SC0CR1

	ldaa	#%00001100		; it does this by setting the proper bits in the
	staa	SC0CR2			; serial control register 2

*					; set 9600 baud
	ldaa	#$00			; the top register should be 0
	staa	SC0BDH			; so we load it with zero


#ifdef _8MHZ_
	ldaa	#$1a			; this sets 9600 for a 8MHZ HC12
#endif

#ifdef _4MHZ_
	ldaa	#13			; this sets 9600 for a 4MHZ HC12
#endif

#ifdef _4800_
	lsla				; this sets 4800 as the baud rate, by doubling the divider
#endif

	staa	SC0BDL			; baud rate is loaded and will take effect now
*					; turn on the transmitter AND receiver

	rts				; returns

***
;get_char: "serial.asm"
;	Used just to get a character IF there is one there. Does not block or echo.
;	Reg Input:
;		None
;	Reg Output:
;		a = character input
***

					; get_char 
					; returns in the A register a character from the
					; serial receiver IF ONE IS AVAILABLE
					; does not block, does not echo
					; messes with A
get_char:
	ldaa	SC0SR1			; it loads the status register
	anda	#%00100000		; checks the register to see if a character is there
	beq	no_char_rx		; if not it ends
	ldaa	SC0DRL			; otherwise it loads the character into A and then ends
no_char_rx:
	rts				; returns

***
;get_char_wait: "serial.asm"
;	Used to get a character. It will block and wait for one to show up, and it
;	Will also echo back a character if it needs to.
;	Reg Input:
;		None
;	Reg Output:
;		a = character input
***



						; get_char_wait	
						; returns in the A register a character from the
						; serial receiver and waits for it -- blocks
						; messes with A
get_char_wait:
		ldaa	SC0SR1			; polls to make sure it is ready to receive a
		anda	#%00100000		; new character by checking the status bit of RX
		beq	get_char_wait		; this blocks

		ldaa	SC0DRL			; loads A with the contents of the serial port buffer
		cmpa	#08			; if the key is backspace, check
		beq	bs_char_wait		; to see where at in buffer
						; before echoing the backspace
		bsr	put_char		; echo it
end_char_wait:	
		rts
	
bs_char_wait:
		cmpb	#20			; checks to see where at in the buffer
		beq	end_char_wait		; if nothing in the buffer, don't echo
		bsr	put_char		; if something in the buffer, echo


		rts				; return



***
;get_char_wait_noecho: "serial.asm"
;	Used to get a character, blocks and waits for one. However, it will not
;	Echo the character once it is received.
;	Reg Input:
;		None
;	Reg Output:
;		a = character input
***

						; get_char_wait_noecho
						; returns in the A register a character from the
						; serial receiver and waits for it -- blocks
						; messes with A
get_char_wait_noecho:				; this gets a character but does not display
	ldaa	SC0SR1				; it back on the screen. likely this is used
	anda	#%00100000			; to get blocks of code when loading programs
	beq	get_char_wait_noecho		; onto the system. this blocks becuase it polls
	ldaa	SC0DRL				; the status register until ready. then loads
						; the data into A
	rts					; returns

***
;put_char: "serial.asm"
;	Used to send a character out on the serial port
;	Reg Input:
;		a = character to send
;	Reg Output:
;		none
***

						; put_char
						; sends the character in A register out
						; the serial port if possible --
						; it checks the TC flag and blocks until
						; it is set
put_char:
	psha	               			; save A because tc_check messes it up
	bsr	tc_check			; checks TX status register to make sure can
	pula					; transfer. restores status of A
	staa	SC0DRL				; loads A onto the data register to be transfered
	rts					; returns

***
;print_string: "serial.asm"
;	Used to print a null terminated string to the terminal through the serial port.
;	Reg Input:
;		y = address of null terminated string
;	Reg Output:
;		none
***

						; print_string takes the address of the 
						; string to be printed in the Y register 
						; and sends characters to the serial port
						; until a null (0) character
print_string:
	ldaa	0,y				; load the character
	beq	done_ps				; if its a zero, end
	iny					; else increment the Y register
	bsr	tc_check			; wait until the transmiter is done
	staa	SC0DRL				; send it to the transmitter
	bra	print_string			; loop to keep printing
done_ps:	
	rts					; returns


***
;print_number: "serial.asm"
;	Used to print a number to the screen.
;	Reg Input:
;		a = the number to print
;	Reg Output:
;		none
***

						; print number
						; prints in ASCII hex the number in
						; register A
print_number:
     psha					; saves state of A
     anda 	#%11110000     			; get upper nibble for the first number
     lsra                			; shift it right to get the nibble
     lsra
     lsra
     lsra		


     bsr  	pn_doit        			; change A and print it pn_next:
     pula                			; get the next nibble
     anda 	#%00001111    			; mask to do so
     bsr  	pn_doit       			; change A and print it
     rts
pn_doit:
     cmpa 	#$09           			; is it greater than 9?
     bgt  	pn_abcdef      			; if so, print a character
     adda 	#48            			; if not, print a number starting at 48 ASCII
     bra  	pn_print       			;
pn_abcdef:     
     adda 	#55             		; if so, print a letter starting at 55 = 65-10 
pn_print:
     bsr  	put_char       			; print it
     rts					; return


***
;print_address: "serial.asm"
;	Prints an address, or a 4 byte number.
;	Reg Input:
;		x = the address
;	Reg Output:
;		none
***

						; print_address prints the address in X
print_address:
	pshd					; saves state of D
	pshx					; saves state of X
	xgdx					; put X into D -- A and B
	bsr	print_number			; prints whats in A -- MSB

*						* should use TAB here

	pshb
	pula					; puts B into A
	bsr	print_number			; prints whats in B -- LSB
	pulx					; restores state of X
	puld					; restores state of D
	rts					; returns


	
