[comp.sys.handhelds] The HP-48 UART - Basic Usage

bson@rice-chex.ai.mit.edu (Jan Brittenson) (04/15/91)

   I hope the following brief and basic explanation will prove useful
to anyone interested in using the HP-48 UART for serial wire
communication from ML programs. Please e-mail me if you find any
inconsistencies in it.

   This draft, is dated April 14, 1991. Do whatever you wish with it -
publication, printing, and other forms of mass distribution highly
encouraged.

						-- Jan Brittenson
						   bson@ai.mit.edu

 O  /
  \/
  /\  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 O  \


INRODUCTION
-----------

   The HP-48 UART (Universal Asynchronous Receiver-Transmitter) is
capable of simultaneously sending and receiving data at speeds of
1200, 2400, 4800 and 9600 bps (bits per second). This document deals
not with how to communicate from a user or system RPL program, but how
to do so from ML (Machine Language). Only the basics are covered:

	o I/O registers and system data

	o ML routines

	o About communication

	o Sample program



HP-48 UART REGISTERS
--------------------

   The list below describes the registers and memory locations
relevant to the basic UART operation. Each entry consists of a header:

	name.size	#address/access

   The name is a symbolic name. The size is the size rounded up to an
integral nybble. The address is the memory location in a default
system configuration. The access specifices whether the register or
location can read from, written into, or both.



	XMIT.2		#00116/write

	   UART transmitter register. Writing a character to this
	address causes it to be transmitted serially. Make sure the
	transmitter is finished with the previous character before
	writing.


	RECV.2		#00114/read

	   UART receiver register. The most recently received
	character can be found here. Must be read before the next
	character has been received.


	RECVBUF.256	#701FC/read-write

	   256-character serial receive buffer. Data is automatically
	added to the buffer via interrupts into system code as they
	arrive in the UART receiver.


	RECVHEAD.8	#703FC/read-write

	   8-nybble serial buffer head. Contains size, get, and put
	counters. Use the ML routine at #31289 (see below) to
	obtain the next character.


	USTAT.1		#00112/read

	-------------
	|  |  |RR|XR|	XR: XMIT ready
	-------------	RR: RECV ready
	  3  2  1  0

	   XR is set if XMIT is ready to accept another character,
	otherwise it is cleared. RR is set when a character is
	available in the UART RECV register. Do not alter bits 3 and
	2.


	PACING.1	#70401/read-write

	-------------
	|XH|  |RH|RF|	XH: XMIT handshaking recognized
	-------------	RH: RECV handshaking used
	  3  2  1  0	RF: XOFF transmitted

   	   Bits 0 and 2 must not be modified, as they are RAM shadows
	for location #0011A. Handshaking on the HP-48 is implemented
	in software. The RF bit signals that the RECV system interrupt
	routine has sent an XOFF to XMIT.


	PACRQ.1		#70402/read-write

	-------------
	|RF|  |  |  |	RF: XOFF transmission requested
	-------------
	  3  2  1  0

	   The RF bit is set when RECVBUF is almost filled up but XMIT
	is busy. This bit should be checked before a character is
	transmitted.


	PARITY.1	#70403/read-write

	-------------	PE: Parity enable, 0 = None
	|PE|P2|P1|P0|	
	-------------	P2 P1 P0
	  3  2  1  0	 1  0  0	Even 2
			 1  0  1	Odd 1
			 1  1  0	Spc 4
			 1  1  1	Mark 3

	   P0-P2 must all be zero if no parity is used. Parity is
	implemented in software on the HP-48, and is resolved before
	characters are added to RECVBUF (see above). For transmission,
	the ML routine at #3113D (see below) can be used to adjust
	bits 0-7 of register A according to the current parity
	setting.


	BPS.3		#0010D/read-write

	   11-bit register specifying the current serial transmission
	speed.

		Value	Speed, BPS

		 #600	  9600
		 #400	  4800
		 #200	  2400
		 #000	  1200

	   Bit 3 of #10E is used for other purposes, and care must be
	taken not to alter it. Both receiver and transmitter operate
	at the same speed.


	UINTR.1		#00110/read-write

	-------------	RI: RECV interrupt
	|RI|RE|XI|XE|	RE: RECV interrupt enable
	-------------	XI: XMIT interrupt
	  3  2  1  0	XE: XMIT interrupt enable

	   UART interrupt register. The RE bit enables RECV
	interrupts, which are triggered when a character becomes
	available in the RECV register. XE enables XMIT empty
	interrupts, which are triggered whenever XMIT is ready for a
	new character. The RI and XI bits are set whenever a RECV and
	XMIT interrupt has been triggered. They are checked by the
	system interrupt handler to determine the cause of the
	interrupt.



ROM COMMUNICATION ROUTINES
--------------------------

	#310CA	Check if UART XMIT ready for another character.
		Checks bit 0 of USTAT.

	    Out:
		Carry	Clear if ready


	#3113D	Add parity to character according to current
		parity setting. Parity of RECV characters can
		be checked by saving the character, calling this
		routine, and then comparing the results. They
		should be equal. All 8 bits are left alone if
		parity is `none.'

	    In:
		A.B	Character

	    Out:
		A.B	Character with parity bit in bit 7


	#31289	Get next character from the serial buffer.

	    Out:
		A.B	Character
		Carry	Set if buffer is empty


	#31085	Check if receive buffer is full. That is, if
		there isn't room for one more character.

	    Out:
		Carry	Set if buffer is full.



COMMUNICATION
-------------

   Character reception is done by an interrupt routine. Whenever a
character is ready in the UART RECV register, an interrupt is
triggered, and a call to the commmoninterrupt entry in the ROM is
made. The interrupt handler in ROM looks at the UINTR bits to find the
cause of the interrupt; if it was RI, then a dispatch to the RECV
interrupt handler is made. The RECV handler retrieves the character
and adds it to the buffer. If there are less than 16 characters
available, it attempts to transmit an XOFF, if handshaking (see the
PACING location) is enabled. If the transmitter is busy, it instead
flags an XOFF request in the PACRQ location. Thus, a program
transmitting data has to check this flag before each successive
character is transmitted; if it's set, an XOFF should be transmitted.

   No XMIT interrupt handler exists in ROM, and no user handler can be
added. It is debatable whether this is useful for implementing light
sleep between transmitted characters. Or rather, how useful that would
be. I do not know whether the UART is operational in light sleep,
or whether it has the option of remaining so.

   In general, it is much more desirable to deal with RECVBUF via the
ROM routines than dealing with the raw operation of the RECV I/O
register. Still, I can conceive of at least one possible instance
where dealing with the RECV register directly is desirable. That is if
the receiver can operate in light sleep, and you don't want to be
woken up from your light sleep by incoming serial data. In such a case
it may be desirable to generally keep RECV interrupts disabled and
employ polling.

   There isn't any XOFF detection in the RECV interrupt handler. The
code that does the transmission has to check whether the next
character in RECVBUF is an XOFF. This seems like a flaw to me - the
`MS-DOS XON/XOFF syndrome.' It breaks when XOFF is not the first
character in RECVBUF and further transmission is required before
RECVBUF is cycled through. Instead, the RECV interrupt handler should
have checked for XOFF (if enabled) and a RAM bit used to flag a paused
condition to the transmitting code.


A SAMPLE PROGRAM
----------------

   The following sample program (STAR syntax) creates a loopback.
Whatever is received in RECVBUF is echoed on XMIT. The program ignores
parity and RECV interrupt handler XOFF requests. Can you think of a
way to add these features?


getc_srecvbuf_a_p = 0x31289
uart_xmit_rdy_p = 0x310ca
xmit = 0x116

echo:
	call	getc_srecvbuf_a_p	; A.B = RECVBUF character
	brcs	echo			; RECVBUF empty - loop
	move	a, r0			; R0.B = character
$100:
	call	uart_xmit_rdy_p		; XMIT RDY?
	brcs	$100			; Nope - loop until it is
	move.5	xmit, d0
	move	r0, c
	move.b	c, @d0			; XMIT = character

	jump	echo			; Echo next character



[This line and the signature below are not part of the document.]

						-- Jan Brittenson
						   bson@ai.mit.edu

akcs.jwtrav@hpcvbbs.UUCP (John Wettroth) (04/21/91)

This is absolutely tremendous information, I can hardly wait to log off
and play around with it, thank you.  Jan, I sent you a few dollars in the
mail to send me a copy of star, please don't forget.  I am looking
forward to it so I can do the kind of low-level hacking that you describe
above.  thanks in advance.