[comp.sys.apple2] Timing problem

dat33228@uxa.cso.uiuc.edu (07/25/90)

  What's the best way to execute a 2 microsecond delay from 16 bit native mode
(65816) when you don't know what your processor speed is?  I want to place
a delay between two toggles of an annunciator (game connector) on the IIgs,
and I want a steady pulse time regardless of whether I'm in normal, fast, or
transwarp mode.  Should I opt for an external hardware device or can I check
one of the internal clocks?  This program will ultimately end up in the
heartbeat manager, interrupts by VBL every 16.6667 milliseconds.


--
..............................................................................
                                                                             .
 Derek Taubert --> derek@mrcnext.cso.uiuc.edu  ||  dat33228@uxa.cso.uiuc.edu .
 Anyone who programs or has an idea for a program for the IIgs, PLEASE send  .
 me mail!                                                                    .
..............................................................................

dlyons@Apple.COM (David A. Lyons) (07/25/90)

In article <1990Jul24.170152.13125@ux1.cso.uiuc.edu> dat33228@uxa.cso.uiuc.edu writes:
> What's the best way to execute a 2 microsecond delay from 16 bit native mode
>(65816) when you don't know what your processor speed is?  I want to place
>a delay between two toggles of an annunciator (game connector) on the IIgs,
>and I want a steady pulse time regardless of whether I'm in normal, fast, or
>transwarp mode. [...]

How 'bout forcing 1 MHz mode temporarily, around the code that turns the
annunciator on and off?

  phb
  pea $e0e0
  plb
  plb           ;saved old B and set B = $E0

  sep #$20      ;8-bit A register

  lda $C036
  pha
  and #$7f
  sta $C036     ;force 1MHz and keep old speed on stack

  sta $C059     ;turn on the pulse(?)
  sta $C058     ;turn off the pulse(?)

  pla
  sta $C036     ;restore old speed

  rep #$20      ;back to 16-bit A register

  plb           ;restore old B register

I'm not staring at a timing chart at the moment, but the accesses to
$C059 and $C058 should give you about a *four* microsecond delay at
1 MHz.  If you really want closer to 2uS, you can use this technique
instead (direct-page addressing to access the softswitches):

  phd           ;save old D
  lda #$C000
  tcd           ;direct page is $C000..C0FF
  sta <$59
  sta <$58
  pld           ;restore old D

This is still 3 cycles per byte.

If you *really* want a shorter pulse than that, in 1 MHz mode (which is
the only mode you can force easily), you could try this.  Summary: Make
the processor access $C059 and $C058 consecutively by doing a stack
operation.  These softswitch accesses are in bank $00 this time, which
is fine as long as I/O shadowing is turned on (and it *has* to be for
interrupts to work!).

  php           ;save old interrupt state
  sei           ;make DAMN sure no interrupts come through now!
  tsx           ;save old stack pointer
  lda #$C05A    ;one byte past where we want to write
  tcs           ;put the stack pointer there
  pha           ;pushes 2 bytes on the "stack" at $C059 and $C058
  txs           ;put the old stack pointer back
  plp           ;restore old interrupt state (and other flags)

This ought to get you a ONE microsecond pulse.  If that's *too* short,
try this for 2:  replace PHA with SEP #$20, PHA, PHA, REP #$20 or,
better yet, replace PHA with PHB PHB.
-- 
David A. Lyons, Apple Computer, Inc.      |   DAL Systems
Apple II Developer Technical Support      |   P.O. Box 875
America Online: Dave Lyons                |   Cupertino, CA 95015-0875
GEnie: D.LYONS2 or DAVE.LYONS         CompuServe: 72177,3233
Internet/BITNET:  dlyons@apple.com    UUCP:  ...!ames!apple!dlyons
   
My opinions are my own, not Apple's.

rond@pro-grouch.cts.com (Ron Dippold) (07/26/90)

In-Reply-To: message from dat33228@uxa.cso.uiuc.edu

Got to thinking about my comment re: your timing problem again...  I had
thought you wanted a continuous pulse, but then I reread it and realized you
only want a one-shot...

My suggestion would be to go to normal mode, do your thing, then return to
whatever mode you were in.  That way you can get an exactly 2 microsecond
(well, 2.046 microsecond) timer.  All you need is:
 
  lda ($e0),y    ; y has zero, $e0 has $5r, $e1 has $c0 (annunciator 3)
  lda ($e2),y    ; $e2 has $5e       $5F^^^  , $e3 has $c0

if you don't want to get into any IIgs stuff.  If you do, then
  phd           ; save direct page
  pea $c000     ; make $c000 direct page
  pld
  lda $5F       ; turn it on
  lda $5E       ; turn it off
  pld           ; restore old direct page
 
 
I still think the best way to do it would be a one-shot timer, where you could
turn off the annunciator to prime it, then turn it on for a 2 msec pulse.  You
wouldn't need to worry about what speed you were running at.
 

UUCP: crash!pro-grouch!rond
ARPA: crash!pro-grouch!rond@nosc.mil
INET: rond@pro-grouch.cts.com