Re: Interface progress and issues

From: Spiro Trikaliotis (ml-cbmhackers_at_trikaliotis.net)
Date: 2004-06-12 12:09:31

Hello Jim,

* On Thu, Jun 10, 2004 at 01:22:00AM -0500 Jim Brain wrote:
 
> For reading of files using GET# and such, I found the CBM would simply
> drop ATN when it had enough data to fulfill the request.

Hu? The ATN is dropped immediately after an OPEN, CLOSE, LISTEN/TALK or
UNLISTEN/UNTALK (with perhaps the secondary address) is sent. If you
want to send something, you have to wait for the listener to signal
"ready" (see, for example, wait_for_listener() in CBM4LINUX, or
$ED5A-$ED5E in the C64 ROM disassembly, or $E94B-$E957 in the Floppy
1541, ROM -03 and -05). The TALKer sets CLOCK to LOW to signal it
wants to send, and the LISTENer can hold this until it sets DATA to
HIGH. The programmer's reference guide has a good diagram of this in
chapter 6, "the serial bus". Look for T_H ("Listener hold off"). So,
there is no need to send bytes more than once.

 
> As of right now, I seem to be having one issue that shows up when 
> sending the command channel results back to the interface.  FOr some 
> reason, my code wants an extra byte to be sent after the EOI character 
> (the last char to be sent).  Due to the way I wrote the interface code, 
> sending an extra 0 doesn;t hurt, but I need to figure out what the issue 
> is at some point.

As the EOI is sent *before* the last byte (the TALKer does not set the
clock after at most 200 us after the LISTENer signalled "I'm ready" by
setting DATA to HIGH, as above, with CLOCK going low (T_NE, "Non-EOI
repsponde to RFD"), but waits for the LISTENer to recognized this and
signalling it with putting DATA again to LOW after T_YE, "EOI Response
time", for T_EI, "EOI Response Hold Time", you have to send a byte after
the EOI.

Have a look how the C64 kernal handles this: The "real" output to the
bus is at $ED40. Anyway, $EDDD (which is called from the kernal jump
table, $FFA8) wraps around it so that is delays the output by 1 data
byte:

$EDDD BIT $94
$EDDF BMI $EDE6
$EDE1 SEC
$EDE2 ROR $94
$EDE4 BNE $EDEB
$EDE6 PHA
$EDE7 JSR $ED40
$EDEA PLA
$EDEB STA $95
$EDED CLC
$EDEE RTS

$94 is negative whenever there is already a byte buffered. So, at start,
it is positive, so $EDE1/$EDE2 set it to negative. $EDE4 is
non-conditional, as Z=0 is always true here, so $EDEB stores the byte
to $95 and returns without any error.

The next time $EDDD is called, $94 is negative, this $EDDF jumps to
$EDE6, which remembers the current byte to be output on the stack,
outputs THE BUFFERED byte ($ED40 does not look at the Accu, but at $95),
gets the new byte and stores it to $95. This way, there is no need to
output an extra byte.

 
> Does a DOS command get executed upon receipt of EOI char, or when 
> UNLISTEN is sent?

I have not checked too deeply (in fact, the 1541 side really is a mess,
compared with the C64 part), but it seems to me that it is executed
immediately after the EOI is recognized: The routine started at $E85B
which handles the IEC bus goes to $E8E7 when a LISTEN has been
encountered (via E8A9-E8B5, E8D2, E8E3, E8E7). Then JSR $EA2E gets the
data bytes from the IEC bus into the command buffer. For this, it jump
to $CFB7 (at EA48) which iteself is the only routine that sets $0255,
the flag for the main loop that there is a command. $0255 is
incremented, whenever there is an EOI signalled ($CFE8-CFF0) with a zero
value in $F8.

$0255 is used in the main loop (EBF0-EBF7) to find out if there is any
command. If yes, EBFC handles it by calling C146. (CFEE, EBF1, EBF8 are
the only locations where 55 02 is there in the 1541's ROM -03).

I do not see the necessity for an UNLISTEN before, but I'm willing to be
corrected.

I tried with VICE and true drive emulation: I set breakpoints to
UNLISTEN ($E88B), the command execution call at $EBF5, and the store to
$0255 at $CFED. My ideas seems to be supported, although I always
received the UNLISTEN before the command was executed. That is because
$EA2E-$EA56 calls $E9C9 to get a data byte from the bus, which itself
tests for ATN. Thus, the UNLISTEN is processed before the main loop is
called again.

I disable the sending of UNLISTEN on the C64 side by putting RTS at
$EDFE.  $CFED was not called after this, unless a CLOSE 1 was executed.
(I excuted open 1,8,15,"v0" for these tests, as well as CLOSE1.)
Thus, something in my logic is wrong: Without the UNLISTEN, the 1541
does not recognize the command.

I checked again: OPEN1,8,15,"V0": $CFED was not called. OPEN
2,8,15,"I0": Now, $CFED was called. It seems that the processing of the
commands need a subsequent ATN, whatever it is (LISTEN, UNLISTEN, TALK,
UNTALK). Good, point taken.

> It looks like you can use channel 0 and 1 in regular open commands, but 
> 0 must be used for reading, and 1 must be used for writing.  Can someone 
> confirm?

Yes, channel 0 assumes ",P,R" at the end, while channel 1 assumes
",P,W".


> If you get a LISTEN, then a TKSA, what should you do?

Signal an error, do nothing. IMHO, this is a clear violation of the
protocol, so you have to assume that something went wrong. Do not do
anything with the bus unless you are "opened" (LISTEN, TALK, OPEN,
CLOSE) again.

> If you get a LISTEN, then a SECOND, then a TALK/TKSA, what do you do?

Whenever you get a LISTEN or TALK, it "overrides" the previous state.
Have a look at the 1541's kernal at $E89B-$E8A7: Whenever a TALK has
been recognized ($E89B-E89D), the TALK state is set ($E89F-E8A1) and the
LISTEN state is reset (E8A5-E8A7). For LISTEN, it is quite the opposite
($E8A9-E8B5).


> And, to save space, there's a theme going here.  Do you use the last 
> commands received, or do you error out?

I don't understand this question.

HTH,
   Spiro.

-- 
Spiro R. Trikaliotis
http://www.trikaliotis.net/

       Message was sent through the cbm-hackers mailing list

Archive generated by hypermail pre-2.1.8.