Article 5921 of comp.sys.handhelds: Path: en.ecn.purdue.edu!noose.ecn.purdue.edu!samsung!think.com!snorkelwacker.mit.edu!ai-lab!rice-chex!bson From: bson@rice-chex.ai.mit.edu (Jan Brittenson) Newsgroups: comp.sys.handhelds Subject: The HP-48 UART - Basic Usage Message-ID: <14901@life.ai.mit.edu> Date: 15 Apr 91 02:24:49 GMT Sender: news@ai.mit.edu Organization: nil Lines: 285 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