<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
Date   : Sun, 30 Oct 2005 00:55:57 +0100
From   : Tom Seddon <tom@...>
Subject: Re: BBC using 3.5 high density format

Greg Cook wrote:
> Supposing the HD controller board only raises NMI on a data request (by
> not connecting INTRQ), all the service routine need do is fetch the
> value, store it and increment the address.  To do a disc operation we
> issue a single sector command then poll the status register and the
> ESCAPE flag until the operation is terminated.  The concept has been
> demonstrated in EDOS and has worked for me flawlessly. 
> 
> For more speed, we can rewrite the EDOS polling loop to disable
> interrupts and use only the Y register, then the NMI routine can use
> indexed addressing without saving A or X.  (The accumulator is needed
> as there is no indexed, absolute STX or STY instruction.)  This does
> however mean providing a 128 byte lookup table to replace ROR.
> 
> 
>>That's not many 6502 instructions, and half as many at HD,
> 
> 
> The nominal data rate at high density is 32 cycles per byte at 2 MHz; a
> minimal NMI routine will keep up with such a controller, or at least
> stay re-entrant under worst case timings.  The routine for reading
> could be, for instance:
> 
> .nmir     LDA fdc_data
> .nmira    STA target,X    \target MOD 256 = 0
>   INX
>   BEQ nmirb
>   RTI
> .nmirb    INC nmira+2
>   RTI

I have an idea.

You could save off the pre-NMI stack pointer, and replace the RTI with 
TXS. This would be a saving of 5 cycles over RTI. The end of the NMI 
routine would then be a series of NOPs, followed by a JMP back to where 
you came from in the ROM. For every byte other than the last, the NMI 
routine would then be re-entered before it got there. The return address 
on the stack would generally be bogus, but you don't care, because you 
don't use it -- and the TXS has anyway restored the stack pointer to the 
value it had before any NMIs happened at all.

According to my calculations, you could then relax the page-alignment 
requirement, so you can if possible read a whole track directly into its 
final location. For reading less than one track, though, you'll have to 
read sector-by-sector, and you'll need an intermediate buffer if reading 
less than a whole sector, for there's no time to cancel the operation 
once it's started :-|

The NMI routine would go a bit like this:

       \ +7 (7) -- NMI overhead
&D00       LDA FDC_DATA \ +6 (13)
       STA (&C0),Y \ +6 (19)
       INY \ +2 (21)
       BNE NO_BUMP:INC &C1 \ +7 (worst case) 28 <-- point A
       .NO_BUMP TXS \ +2 (30)
       NOP \ +2 (32)
       NOP:NOP:NOP \ +6 (cater for best-case timings)
       NOP \ the lucky NOP
       JMP READ_END

(At point A, you'd otherwise have no time for the RTI, because you'd be 
3 cycles out by the time it finished. This would eventually throw the 
timings out of whack.)

This gives you enough time -- just -- to cope with writing data into the 
1MHz I/O area. That's the rationale behind the extra NOPs: whilst I've 
listed the worst-case timings (writing a byte into the I/O area on the 
"wrong" cycle, combined with bumping the current page), in the best case 
you've got these extra 6 cycles.

Due to the interrupts' having being cleared, you should be guaranteed 
that ROMSEL is preserved during the operation, so there's no need to 
restore it before returning to the ROM routine.

Note also the extra 2 cycles for the initial LDA; I can't remember 
whether reads incur cycle stretching when fetching bytes from the FDC, 
so I added in 2 anyway. That's what my lucky NOP is for :)

The DFS code would then be something like:

       SEI
       \ copy in NMI code
       \ store destination address in &C0
       LDY #0
       TSX
       LDA #XX:STA FDC_CTRL \ hand-wavy "start operation" bit
       .WAIT JMP WAIT
       .READ_END
       CLI
       \ determine whether we're here because of an error,
       \ or because the operation completed successfully

With apologies for the hand-waving details about how you start the 
actual operation off... I can't remember that bit...

--Tom

P.S. I'm pretty sure that the timings would hold up for writing to disc 
too. In fact, in the absence of a page crossing, I think you'd be 1 
cycle better off... better add another lucky NOP ;)
<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>