It was thus said that the Great Sellam Ismail once stated:
On Thu, 2 Jan 2003, Dwight K. Elvey wrote:
I'm
trying to troubleshoot a more pressing problem right now: the reader
is picking 5 cards before the Apple thinks 80 Index Marks (e.g. 80
characters) have been detected. Either my code is wrong, my code is slow,
or the Apple is too slow to handle the reader input (in which case this
was all for naught).
It sounds like something is wrong. Are you reading with BASIC
or at code level. I would think that assembly code should be able
to keep up, as long as you were not expecting it to transfer to
disk while reading. Does the M200 have any kind of handshake?
I'm not so sure. Here's what I know:
6502 operates at roughly 1,000,000 cycles per second.
I wrote a very tight code loop to simply look for the READY signal from
the reader, and then count Index Marks, as quickly as it can. Here's the
relevant loop code (the number is parentheses at the end of the comment
is the number of cycles that instruction takes):
LDX #$00
LOOP LDA $C0C1 ; Get the data at 6522 Port A (4)
AND #$08 ; Bit 4 is the RDY signal input (4)
BEQ LOOP ; Loop until it goes true (2)
WAIT LDA $C0C1 ; Now wait until it goes false (4)
AND #$08 ; (4)
BEQ WAIT ; (2)
INX ; Increment the count (2)
INC $06 ; Increment a zero page location* (6)
CPX #$50 ; 80 Index Marks yet? (4)
BNE LOOP ; No? Keeping looping (2)
First off, while I can't say this for sure on the 6502, I do know that the
6809 had two cycle counts for the various branches; one for branch taken and
one for not (although that may have been for the long branches---my
reference material is packed away somewhere), so you may be one or two
cycles off your count.
Now, going through the code:
LOOP LDA $C0C1 ; (4)
AND #$08 ; (4)
BEQ LOOP ; (2) - loop back if bit is zero
WAIT LDA $C0C1 ; (4)
AND #$08 ; (4)
BEQ WAIT ; (2) - loop back if bit is zero
Now, are you *sure* that is what you want? Your comments on LOOP make
sense---wait until the bit goes 1, but for WAIT, you say you are waiting
until it goes zero, but the code doesn't match that comment.
That might be your problem right there.
Since my 6502 reference is packed away (sigh---most of my computer
reference is packed away) does the INX/DEX instructions affect the flags?
If so, you may be able to shave some time off:
LDX #80
LOOP LDA $C0C1 ; (4)
AND #$08 ; (4)
BEQ LOOP ; (2) (10 per loop)
WAIT LDA $C0C1 ; (4)
AND #$08 ; (4)
BNE WAIT ; (2) (10 per loop-bug fix as well?)
INC $06 ; (6)
DEX ; (2)
BNE LOOP ; (2)
Save four cycles if DEX does affect the flags.
* So I can view the resulting value when I reset the
computer to break out
of the loop
So counting up the cycles to read the index mark, it's 10 to wait for it
to go true, 10 for it to go false, then 14 to increment a counter and go
back to the top of the loop.
The timing diagram of the M200 says that the Index Mark is pulsed for 6
microseconds. Now, if I'm computing this right, that is already less time
than it takes for the 6502 to wait for the pulse to fall back to false
from true. The 6502 takes 10 cycles, or roughly 10 microseconds, assuming
a cycle is equivalent to a microsecond.
Can you change the location of the status bit? If you can make it so that
bit 7 of $C0C1 is the status bit you can save four cycles per loop:
LOOP LDA $C0C1 ; (4)
BPL LOOP ; (2) wait until status bit goes high
WAIT LDA $C0C1 ; (4)
BMI WAIT ; (2) wait for status bit to go low
I think the 6502 sets flags on loading the accumulator; if so, then
changing the status bit to be bit 7 will cause the Negative Flag to reflect
the state of bit 7---this gets rid the explicit compare and brings you
within range.
-spc (But better check the flags for each instruction)