Sub-pages
Serial Port Overview
The Amiga includes a standard RS232 serial port managed by a UART (Universal Asynchronous Receiver/Transmitter) built into the Paula custom chip. The port supports full-duplex communication — data can be transmitted and received simultaneously over separate signal lines.
The RS232 connector carries two categories of signals:
- Data signals — TXD (transmit data) and RXD (receive data), which carry the actual serial bitstream.
- Handshake signals — CTS, RTS, DSR, DTR, etc., which are managed through the CIA chips and were covered in the CIA documentation.
All serial data transfer takes place over the TXD and RXD lines. When connecting two devices, TXD on one device is wired to RXD on the other and vice versa (null-modem / crossover wiring).
RS232 Data Format
Since only a single wire carries data in each direction, bytes must be serialized bit-by-bit. Because RS232 has no separate clock signal, both sender and receiver must agree on the bit timing — the baud rate, which specifies the number of bits transferred per second. Common baud rates are 300, 1200, 2400, 4800, and 9600.
Each byte is framed as follows:
- Start bit — a transition from the idle (high) state to low, signaling the beginning of a byte.
- Data bits — transmitted LSB first, in 8-bit or 9-bit format.
- Stop bit(s) — one or two high bits marking the end of the byte.
The receiver detects the start of each byte by the high-to-low transition between the stop bit of the previous byte and the start bit of the new one.
UART Registers
The UART in Paula uses three registers for serial data transfer, plus one bit in the ADKCON register for break control.
SERDATR — Receive Data and Status ($DFF018, read)
This register contains both the received data byte and status flags for the UART.
SERPER — Period Register ($DFF032, write)
Receiving Data
Serial reception proceeds in two stages, using a shift register and a data buffer.
Stage 1: Shift Register
Incoming bits on the RXD pin are clocked into a shift register at the rate determined by SERPER. The start bit triggers the process: the UART samples RXD at the center of each bit period to reconstruct a parallel data word.
Stage 2: Data Buffer
When the shift register is full (all data bits plus stop bit received), its contents are transferred to the receive buffer — the data bits in SERDATR. The shift register is then immediately free to begin receiving the next byte.
Data Format
The data width depends on the LONG bit in SERPER:
- LONG = 0 (8-bit mode): Bits 7–0 of SERDATR contain the 8 data bits. Bit 8 holds the stop bit. Bit 9 holds the second stop bit (if present).
- LONG = 1 (9-bit mode): Bits 8–0 contain 9 data bits. Bit 9 holds the stop bit.
Status Flags
RBF (Receive Buffer Full) is set to 1 when a complete data word is transferred from the shift register to the buffer. This flag also exists as bit 11 in INTREQ/INTEN, generating an interrupt. After reading the data, software must clear RBF by writing to INTREQ:
move.w #$0800,$DFF09C ; clear RBF in INTREQ (and SERDATR)
Overrun Detection
If the receive buffer is not read before the shift register fills again, an overrun occurs. The OVRUN bit in SERDATR is set to 1, indicating that data has been lost. When RBF is finally cleared, the shift register contents are transferred to the buffer and OVRUN is reset. RBF then goes high again immediately, since the buffer now contains the (late) data from the shift register.
To avoid overruns, always read SERDATR and clear RBF promptly — ideally in an RBF interrupt handler.
Transmitting Data
Serial transmission also uses a two-stage pipeline: a data buffer (SERDAT) and an output shift register.
Writing Data
The transmit data format in SERDAT depends on the desired word length and number of stop bits. The data bits occupy the lower portion of the register, followed immediately by one or two stop bits (set to 1). All higher bits must be 0.
8-bit data, 2 stop bits:
8-bit data, 1 stop bit:
9-bit data, 1 stop bit:
Note that the LONG bit in SERPER only affects reception. The transmit format is determined entirely by the value written to SERDAT.
Transmit Status Flags
TBE (Transmit Buffer Empty) is set to 1 when the data in SERDAT has been transferred to the output shift register. The buffer is then ready for the next word. TBE is also bit 0 in INTREQ/INTEN. Like RBF, it must be cleared via INTREQ after servicing.
TSRE (Transmit Shift Register Empty) is set to 1 when the shift register has finished sending all bits and no new data is waiting in the buffer. This indicates that the transmission is truly complete. TSRE is reset when TBE is cleared.
UARTBRK — Break Signal
Bit 11 (UARTBRK) of the ADKCON register, when set, forces the TXD output line low and halts serial transmission. This generates a "break" condition on the RS232 line, which the remote device can detect. Clear the bit to resume normal operation.
Baud Rate Calculation
The lower 15 bits of SERPER (bits 14–0, the RATE field) specify the bit period as a number of bus clock cycles. One bus clock cycle lasts approximately 279.365 nanoseconds (based on the PAL system clock of 3.546895 MHz).
The formula to convert a desired baud rate to the SERPER value is:
Or equivalently:
Common Baud Rates
The calculated value is rounded to the nearest integer before writing to SERPER:
move.w #745,$DFF032 ; set 4800 baud (NTSC), LONG=0 (8-bit)
For 9-bit receive mode, set bit 15:
move.w #$8000+745,$DFF032 ; set 4800 baud, LONG=1 (9-bit receive)
Interrupts and Programming
The UART generates two interrupt signals, both managed through INTREQ/INTEN:
Typical Receive Handler
SerialReceiveISR:
move.w $DFF018,d0 ; read SERDATR
btst #15,d0 ; check OVRUN
bne .overrun ; handle overrun condition
and.w #$00FF,d0 ; extract 8 data bits
; ... process received byte in d0 ...
move.w #$0800,$DFF09C ; clear RBF in INTREQ
rte
.overrun:
move.w #$0800,$DFF09C ; clear RBF to recover
; ... signal overrun error ...
rte
Typical Transmit Sequence
SendByte:
; d0.b = byte to send
and.w #$00FF,d0 ; mask to 8 bits
or.w #$0100,d0 ; add 1 stop bit (bit 8 = 1)
move.w d0,$DFF030 ; write to SERDAT
; TBE interrupt will fire when buffer is free for next byte
rts
The UART in Paula handles start bit insertion and bit serialization automatically. Software only needs to write the data word (with stop bits) to SERDAT and wait for TBE before sending the next byte.