Zilog SIO & Receive Interrupts

54 views
Skip to first unread message

Jon Jones

unread,
Oct 13, 2025, 2:56:39 AMOct 13
to retro-comp
I’m playing with the SIO & Interrupts. Transmit is working fine.

Receive is “interesting”.

At first I was setting "RX interrupt on first character" on Register 1 and at the end of the interrupt handler, setting "Enable Interrupt on next receive character” on Register 0. But all I was receiving was the first character. The handler would never be triggered again.

If I set Register 1 to “Interrupt on all RX” (without touching Register 0 at the end of the handler) then I do get all the characters.

What have I misunderstood about the first scenario where I could not get interrupts on subsequent characters?

In both scenarios, the interrupt handler doesn’t assume there’s only one character to receive and instead loops to make sure it receives every character before returning.

There’s also a second question of: What’s the difference between the two methods?

Jon.

ladislau szilagyi

unread,
Oct 13, 2025, 6:14:48 AMOct 13
to retro-comp
Hi,

here is how I setup SIO/2, for IM 2 mode interrupts (Receive & Transmit)

SIO_A_TAB:
defb 00011000B ;WR0 Channel reset
defb 00010100B ;Wr0 Pointer R4 + reset ex st int
defb 11000100B ;Wr4 /64, async mode, 1 stop bit, no parity
defb 00000011B ;WR0 Pointer R3
defb 11100001B ;WR3 8 bit, Auto enables, Receive enable
defb 00000101B ;WR0 Pointer R5
defb 11101010B ;WR5 DTR, 8 bit, Transmit enable, RTS
defb 00010001B ;WR0 Pointer R1 + reset ex st int
defb 00011010B ;WR1 interrupt on all RX characters, TX Int enable
SIO_A_END: ;parity error is not a Special Receive condition

SIO_B_TAB:
defb 00011000B ;WR0 Channel reset
defb 00000010B ;WR0 Pointer R2
defb 00010000B ;WR2 interrupt address = 10H
defb 00010100B ;Wr0 Pointer R4 + reset ex st int
defb 11000100B ;Wr4 /64, async mode, 1 stop bit, no parity
defb 00000011B ;WR0 Pointer R3
defb 11000000B ;WR3 8 bit
defb 00000101B ;WR0 Pointer R5
defb 01100000B ;WR5 8 bit
defb 00010001B ;WR0 Pointer R1 + reset ex st int
defb 00000100B ;WR1 no INTS on channel B, status affects INT vector
SIO_B_END: ;INTs: BTX,BE/SC,BRX,BSRC,ATX,AE/SC,ARX,ASRC
;
; SIO (async)
;
; Init SIO
;
ld hl,SIO_A_TAB
ld c,SIO_A_C ;SIO_A
ld b,SIO_A_END-SIO_A_TAB
otir
;HL=SIO_B_TAB
ld c,SIO_B_C ;SIO_B
ld b,SIO_B_END-SIO_B_TAB
otir
;

It works well in my RTM/Z80 system...

Ladislau

Douglas Miller

unread,
Oct 13, 2025, 7:26:05 AMOct 13
to retro-comp
The Z80-SIO documentation states for command 100b:

        Command 4 (Enable Interrupt On Next Receive Character). If the Interrupt
        On First Receive Character mode is selected, command 4 reactivates the
        Enable Interrupt On Next Receive Character mode after receiving each
        complete message. This sequence prepares the Z80 SIO for the next message.

This suggests to me that this command is NOT for character-by-character receive interrupts, but is for re-arming the "first character interrupt" mode. I'm not sure what it means by "message" here, though.

I have used "interrupt on first Rx char" in a "wake up" mode where the port was normally not even connected to anything, but if a terminal was connected and a user pressed a character, it activated an "interactive mode". Essentially, on first character the code path diverged and turned Rx interrupts off because it was then switching to polling, and issued a command prompt. But if you want to be interrupted whenever characters are available, you want to set "interrupt on ALL Rx chars". Keep in mind that these interrupts are "level triggered" on (nearly) all systems, and so if your interrupt handler takes as many characters as are available (in the Rx FIFO), you will not get stray interrupts. Once the handler has emptied the FIFO, the interrupt line goes off and your RETI will not immediately be interrupted again.
Reply all
Reply to author
Forward
0 new messages