Jump to content
IGNORED

Waiting for XMTDON


robus

Recommended Posts

Hoping for a bit of help grokking this bit of code:
 

; TRANSMIT DONE INTERRUPT SERVICE ROUTINE
;
ISRTD:  LDA   	CHKSNT
        BEQ     FOOEY ;BRANCH IF CHECKSUM NOT YET SENT
					   ;OTHERWISE SET TRANSMISSION DONE FLAG
					   ;DISABLE TRANSMIT DONE INTERRUPT
						;RETURN FROM INTERRUPT
						; ;
		STA 	XMTDON
		LDA     POKMSK
		AND     #$F7
		STA     POKMSK
		STA     IRQEN
;
FOOEY: PLA
		RTI

 

The OS has tried to send a byte to a Disk device (which of course is not present) and the SEND: block is currently looping on this:

 

NOTDON: LDA 	BRKKEY
		BNE 	NTBRKO
		JMP 	BROKE		;JUMP IF BREAK KEY PRESSED
				
NTBRKO: LDA   	XMTDON 	;LOOP UNTIL TRANSMISSION IS DONE
		BEQ     NOTDON
		JSR     SENDDS 	;DISABLE SENDING
		RTS     RETURN

 

My question is how is a timeout supposed to be handled in this situation? What is POKEY expected to do with a byte it can't send? And how does XMTDON get a value that breaks the loop?

Link to comment
Share on other sites

No timeout is needed as the duration is strictly bounded based on the output bit clock.

 

POKEY asserts the serial output ready IRQ whenever it has loaded the output shift register and is ready for another byte to be queued. At this point, SIO can do one of two things: write another byte into SEROUT, or wait for the serial output complete IRQ. The latter is the case for the code above and is guaranteed to complete, as the duration solely depends on the fixed rate that POKEY shifts out bits based on AUDCTL/AUDF3/AUDF4/SKCTL. As there is no per-byte handshaking on the SIO bus, it doesn't matter what the devices on the SIO bus are doing -- POKEY will send the bits out regardless of whether any device is ready to receive. Waiting for the serial output complete IRQ is needed because it takes time for POKEY to shift out the last byte after it has been loaded into the shift register from SEROUT, and the serial port parameters can't be changed until all bits have sent.

 

As for the serial output complete IRQ itself, it is special in that it is not a latched IRQ. Instead, it's simply asserted whenever the serial output shift register is idle. Thus, its state in IRQST bit 3 is not dependent upon whether it is enabled in IRQEN, and if the output shift register is already idle it will assert an IRQ as soon as it is enabled.

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Thanks, that helps and now I'm sending those IRQs to the CPU as my POKEY blindly shoves the bits out. However the SYIRQ: handler is quite a puzzle.

 

SYIRQ:  PHA					 ;SAVE ACCUMULATOR
          LDA     IRQST	  	; CHECK FOR SERIAL IN
          AND     #$20
          BNE     SYIRQ2
          LDA     #$DF		 ; MASK ALL OTHERS
          STA     IRQEN
          LDA     POKMSK
          STA     IRQEN
          JMP     (VSERIN)
SYIRQ2: TXA					 ;PUT X INTO ACC
          PHA				   ;SAVE K ONTO STACK
          LDX     #$6		;START WITH SIX OFFSET
LOOPM:  LDA   CMPTAB,X   ;LOAD MASK
          CPX     #5		;CHECK TO SEE IF COMPLETE IS SET
          BNE     LOOPM2
          AND     POKMSK	;IS THIS INTERUPT ENABLED?
          BEQ     LL

 

Specifically the LOOPM: section. I see X is loaded with 6 then A is loaded from the mask table (offset by X), and then X is compared to 5, but we know 6 won't ever equal 5 so what is the deal with that bit of logic?! However I think that "CHECK TO SEE IF COMPLETE IS SET" is not related to Transmission complete. That I believe is handled by ISRTD:

; TRANSMIT DONE INTERRUPT SERVICE ROUTINE
;
ISRTD:  LDA   CHKSNT
        BEQ     FOOEY 	;BRANCH IF CHECKSUM NOT YET SENT
  						
 						
		STA XMTDON		;OTHERWISE SET TRANSMISSION DONE FLAG
		LDA     POKMSK	;DISABLE TRANSMIT DONE INTERRUPT
		AND     #$F7
		STA     POKMSK
		STA     IRQEN

FOOEY: PLA
		RTI				;RETURN FROM INTERRUPT

 

Could someone give me the address of ISRTD? I'd like to set a "breakpoint" there to see if it gets called in my simulator. At the moment I believe it isn't.

 

(I wonder if there is a listing of all the subroutine addresses in this ROM?)

Link to comment
Share on other sites

Ah I do see that LL: does DEX and loops around so at least X is changed, though the logic is quite convoluted seeming! :)

 

Anyway, I also see that the Transmission Finished IRQ is not enabled until there's some other IRQ first, (like Output Data Needed). However I'm still not getting out of that loop, going to do some further stepping/debugging.

 

(And I now see that Mapping the Atari has a number of routine addresses listed).

Link to comment
Share on other sites

Hmm, I think my problem is that both Output Data Needed and Transmission Finished are both set and, because of the order of testing which IRQs are ready (in the CMPTABLE), the Output Data Needed JMP is taken. It seems like Output Data Needed would always be available (if the flag is set in IRQEN?) but then ISRTD would never be called, which is obviously not the case.

 

Hoping for some clarity on that?

 

 

Link to comment
Share on other sites

This is my POKEY IRQ status when the Interrupt is handled

 

timer1                  uint8	'\x01'
timer2                  uint8	'\x01'
timer4                  uint8	'\x01'
serialOutputDone        uint8	'\0'
serialOutputDataNeeded  uint8	'\0'
serialInputReady        uint8	'\x01'
keyPressed              uint8	'\x01'
breakPressed            uint8	'\x01'


I see that setting bits to 0 in IRQEN is meant to reset the status of some bits (excluding serialOutputDone) and I'm now handling that. I expected it to turn off the serialOutputDataNeeded, but it didn't

Edited by robus
Link to comment
Share on other sites

Yes, POKEY will hold /IRQ asserted as long as there is still an enabled IRQ pending in IRQST. This will cause the 6502 to re-enter the IRQ routine after the RTI until all IRQs are acknowledged. This does mean that if the 6502 fails to handle an IRQ properly, it will get stuck in an interrupt loop, which does occasionally happen. There is no queuing beyond that though -- POKEY doesn't record that it should call the same IRQ twice, nor will the 6502 run the IRQ handler if an unmasked IRQ isn't currently active.

 

As for the interrupt state, you shouldn't have serial output ready and serial output complete both asserted during normal SIO operation unless there is a gap in transmission. That shouldn't happen as the SIO routines will keep one byte queued ahead in SEROUT. Serial output ready only triggers when the output shift register is loaded from SEROUT and won't assert at the end of the last byte.

 

Link to comment
Share on other sites

4 hours ago, robus said:

Specifically the LOOPM: section. I see X is loaded with 6 then A is loaded from the mask table (offset by X), and then X is compared to 5, but we know 6 won't ever equal 5 so what is the deal with that bit of logic?! However I think that "CHECK TO SEE IF COMPLETE IS SET" is not related to Transmission complete.

This branch is related to the special nature of the serial output complete IRQ. All other IRQs are defined to be negated when disabled -- if bit 6 of IRQEN is cleared, the serial output ready IRQ is disabled. Any existing pending IRQ for it is cleared, bit 6 of IRQST is locked to 1, and it cannot recur until re-enabled.

 

However, the serial output complete IRQ is special and will show an active status in IRQST bit 3 even if it is disabled. For this reason, the OS checks if the serial output complete IRQ is actually enabled before trying to handle it. It can't read back from the write-only IRQEN register, so it uses the shadow variable POKMSK instead.

 

Link to comment
Share on other sites

1 hour ago, phaeron said:

Serial output ready only triggers when the output shift register is loaded from SEROUT and won't assert at the end of the last byte.

Thanks for all the help, it is very much appreciated!

 

How does POKEY know it's seen the last byte?

 

Currently, I just set raise the output ready IRQ after POKEY has loaded its "shift register" - so it always thinks there could be another byte (if the IRQ is enabled of course, so I guess the answer is the IRQ is disabled when the last byte is written!)

Edited by robus
Link to comment
Share on other sites

I have to admit that I'm really not grokking this test:

 

LOOPM2: BIT   IRQST ; IS IT THE INTERUPT?
        BEQ     JMPP

Bits in IRQST are at zero when they have triggered, so how does BIT testing against a mask address that?

The mask has $08 for the COMPLETE test, but POKEY sets COMPLETE bit to zero?

Link to comment
Share on other sites

4 hours ago, robus said:

How does POKEY know it's seen the last byte?

 

Currently, I just set raise the output ready IRQ after POKEY has loaded its "shift register" - so it always thinks there could be another byte (if the IRQ is enabled of course, so I guess the answer is the IRQ is disabled when the last byte is written!)

It doesn't. It's just that if there isn't a new byte available in SEROUT, there's nothing to load into the shift register, and thus serial output ready doesn't get triggered. If the 6502 does write a new byte, POKEY loads it on the next serial tick and then triggers serial output ready.

 

This does mean that you need to track an additional boolean state if you haven't already: whether SEROUT holds an unsent byte.

 

3 hours ago, robus said:

I have to admit that I'm really not grokking this test:

 

LOOPM2: BIT   IRQST ; IS IT THE INTERUPT?
        BEQ     JMPP

Bits in IRQST are at zero when they have triggered, so how does BIT testing against a mask address that?

The mask has $08 for the COMPLETE test, but POKEY sets COMPLETE bit to zero?

At this point, the A register holds the IRQ bit to be tested. For the serial output complete IRQ, it is skipped if the POKMSK test fails. The BIT instruction then masks off the value of IRQST to only the pertinent bit by computing the bitwise AND of the IRQ state from IRQST and the bit in the A register. If the bit is cleared, Z=1 and the BEQ is taken to dispatch to the IRQ handler. The loop continues until either it finds an IRQ that is asserted (0 bit) or nothing is found (spurious or non-POKEY IRQ).

 

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...