[comp.sys.apple2] CPU speed detection

barcan@CPSC.UCALGARY.CA (Davor Barcan) (12/06/90)

I'm currently working on an application that is timing dependent.
For example, I'd need to be able to closely estimate a wait for
approximately thirty seconds (this is all hypothetical).  This
isn't necessarily a problem and is easily accomplished with the
Apple II ROM Wait routine; just pop a value into the accumulator
and do a JSR to the routine.

A wrench is thrown into the mechanism when the computer happens
to be accelerated beyond the normal 1 Mhz range of an Apple II.
This is the case when I execute the code on my //e with a 10 Mhz
RocketChip.  I need to know a way to estimate the speed that the
CPU is operating at without being dependent on a certain type of
accelerator.

I know that this is possible because ProTerm doesn't seem to be
bothered by the fact that my CPU is cruising at 10 Mhz.  In fact,
its timing is just like it is when I'm running it at 1 Mhz.  I'm
assuming that ProTerm uses a routine to determine the speed of
the CPU.  One method that I can think of is by using the VBL and
keeping a counter until the VBL changes again.  Would this be an
accurate method?  I'd probably have to keep a very big counter
a very big counter if one happens to be running at 10 Mhz,
assuming that this is an effective method.

There's a further complication in that the VBL is handled
differently on a //e and a GS, and as far as I know the //c
doesn't have a VBL (or at least one that works).  Does anyone
have a procedure for determining CPU speed?  Or better yet,
a wait routine that isn't affected by different CPU rates?

Davor Barcan
barcan@cpsc.UCalgary.CA
University of Calgary

axi0349@isc.rit.edu (A.X. Ivasyuk ) (12/07/90)

In article <9012052301.AA15585@cs-sun-fsa.cpsc.ucalgary.ca>, barcan@CPSC.UCALGARY.CA (Davor Barcan) writes:
> I'm currently working on an application that is timing dependent.

<< stuff deleted>>

> the CPU.  One method that I can think of is by using the VBL and
> keeping a counter until the VBL changes again.  Would this be an
> accurate method?  I'd probably have to keep a very big counter
> a very big counter if one happens to be running at 10 Mhz,
> assuming that this is an effective method.

This should be quite effective, because VBL is guaranteed to change 60
times per second on North American standard Apples.

> There's a further complication in that the VBL is handled
> differently on a //e and a GS, and as far as I know the //c
> doesn't have a VBL (or at least one that works).  Does anyone

The //e has a VBL register at $C019, I believe, which tells the current
state of the VBL.  Bit seven indicates whether you are actually in the
middle of VBL interrupt.  The //gs has a different system, but I don't
know about the //gs, since I don't have access to one.  On my //c,
however, you can have the (built-in) mouse card interrupt your program
every time there is a VBL interrupt and proceed to run an interrupt
routine.  The easiest was to install interrupt routines is through the
ProDOS system calls.  I believe the //e mouse card and the gs mouse
firmware behave in the same way as the //c.  There is a program called
Daemon which is, I believe, shareware, which runs stuff in the
background based on the VBL.  It should be available on FTP and on the
listserv at APPLE2-L (listserv@brownvm.brown.edu).

> Davor Barcan
> barcan@cpsc.UCalgary.CA
> University of Calgary

@@@@  @@@@@ @@@@@         Anatoly Ivasyuk             @@@   @@@  @   @
@   @   @     @      (axi0349@ultb.isc.rit.edu)      @   @ @     @   @
@@@@    @     @        Computer Science House        @      @@@  @@@@@
@  @    @     @   Rochester Institute of Technology  @   @     @ @   @
@   @ @@@@@   @      "If all else fails, RTFM."       @@@   @@@  @   @

mdavis@pro-sol.cts.com (Morgan Davis) (12/07/90)

In-Reply-To: message from barcan@CPSC.UCALGARY.CA

} I'm currently working on an application that is timing dependent.
} A wrench is thrown into the mechanism when the computer happens
} to be accelerated beyond the normal 1 Mhz range of an Apple II.
} One method that I can think of is by using the VBL and
} keeping a counter until the VBL changes again.  Would this be an
} accurate method?

Using the VBL signal is about as accurate as you're going to get.

} I'd probably have to keep a very big counter
} a very big counter if one happens to be running at 10 Mhz,
} assuming that this is an effective method.

Not really.  A two-byte "tick" counter will count ticks from 1/60 second
to about 18 minutes, regardless of the CPU's speed be it 1MHz or 100Mhz.
That kind of range is acceptable for various delays and pauses within a
program.  Adding another byte to your counter brings you up to 77 hours
capacity.

A tick is the amount of time, roughly 1/60 second, between the leading
edge of each VBL signal.  Counting one tick goes something like this:

        ticka   bit     $c019           ; Loop while VBL signal is low
                bpl     ticka
        tickb   bit     $c019           ; Loop while VBL signal is high
                bmi     tickb
                                        ; A full tick cycle has passed here
                <increment counter here>
                <compare counter to delay>
                <if less than, goto ticka>

} There's a further complication in that the VBL is handled
} differently on a //e and a GS, and as far as I know the //c
} doesn't have a VBL (or at least one that works).

Fortunately, reading $C019 in the manner given above works correctly on
both the IIe and IIGS.  Since the IIc doesn't have a polled VBL signal,
you'd have to write a VBL interrupt handler which did your tick counter
incrementing.  On the II+, I designed a method by which a VBL-like signal
can be mapped to a different hardware location ($C060).  The article
describing this scheme was posted a few months ago.  Let me know if you
want it.

} Does anyone have a procedure for determining CPU speed?  Or better yet,
} a wait routine that isn't affected by different CPU rates?

The VBL method is about as clean as you're going to get.  The only other
method I can think of is to make use of some other hardware benchmark
that you might have access to.  For example, (and this certainly isn't
a "clean" method) if you have access to a serial port:

o       Set the port's speed to a known rate (e.g. 300bps)
o       Write a character directly to it (don't use firmware)
o       Begin incrementing a counter until the serial port tells
        you that it is ready for another character

This give yours program a value that will be different on machines with
different CPU rates.  Unfortunately, you won't end up with a perfectly
consistent constant.  You'll have to match what you get with a range of
likely values to determine the approximate CPU speed.  You also aren't
assured of having a serial device to work with (unless your program is
a communications package that requires one).

The last and most undesirable step is to allow the user of your program
to configure it for different speeds.  This is how Talk is Cheap currently
does it, because there really aren't any perfect solutions to this kind
of problem.

} Davor Barcan
} barcan@cpsc.UCalgary.CA
} University of Calgary

--Morgan Davis

UUCP: crash!pro-sol!mdavis           AOL, BIX: mdavis  
ARPA: crash!pro-sol!mdavis@nosc.mil  GEnie:    m.davis42
INET: mdavis@pro-sol.cts.com         ProLine:  mdavis@pro-sol

alfter@uns-helios.nevada.edu (SCOTT ALFTER) (12/08/90)

In article <6129@crash.cts.com> mdavis@pro-sol.cts.com (Morgan Davis) writes:
>Fortunately, reading $C019 in the manner given above works correctly on
>both the IIe and IIGS.  Since the IIc doesn't have a polled VBL signal,
>you'd have to write a VBL interrupt handler which did your tick counter
>incrementing.  On the II+, I designed a method by which a VBL-like signal
>can be mapped to a different hardware location ($C060).  The article
>describing this scheme was posted a few months ago.  Let me know if you
>want it.

All this talk about getting consistent timing at different clock rates
brought up a problem with some telecomm routines I was writing.  I
needed some way to time a hardware BRK signal.  Presently the routine
just uses a tightly-coded loop, but the timing is only valid at 1 MHz.
I figure that on a 60 Hz system, counting 14 ticks of the VBL will
count 233.333333... ms, which is very close to the 233 ms that a
hardware BRK is supposed to last.

A problem crops up with 50 Hz systems (not that I have one, but
someone who might want to use my program might have one).  The time
taken by one tick is longer, so instead of getting something close to
233 ms, 14 ticks will last 280 ms.  Is the timing of a hardware BRK
absolutely critical, or can you have pretty much any length so long as
it's at least 233 ms?

Also, does anybody have a clue how to go about getting a tick counter
running on a IIc?  The IIe/IIGS solution has already been spelled
out--just tack on a few extra bytes to count 14 ticks.  Something was
mentioned about having to use interrupts to count ticks on the
IIc--sounds yucky since it would involve installing and detaching an
interrupt daemon every time you want to send a BRK. :-(

-----------------------------------------------------------------------------
Scott Alfter                             _/_
                                        / v \ Apple II:
Internet: alfter@uns-helios.nevada.edu (    ( the power to be your best!
   GEnie: S.ALFTER                      \_^_/

jh4o+@andrew.cmu.edu (Jeffrey T. Hutzelman) (12/08/90)

VBL is the only technique I can think of, except on the IIgs.  The
IIgs wait routine is independant of system speed, although I don't
know what various accelerators will do to it.  The //c DOES have a
VBL; it just has to be "turned on." by initializing the mouse.  You
can then process VBL interrupts like any other interrupt.  There is a
discussion of how to identify and handle mouse interrupts, including
VBL, in the //c Technical Reference Manual.  I can email the relavent
sections to you, if you want.  Note that this technique does NOT
require that you have a mouse; only that you initialize the moouse
firmware to the "VBL-only" mode.
You CAN determin which CPU type you're on, and use that to figure out
which VBL to use.
Finally, the delay produced by the wait routine is not guaranteed
beyond the fact that it will be at least the time you specify.
--------------------
Jeffrey Hutzelman			America Online: JeffreyH11
Internet: jh4o+@andrew.cmu.edu		BITNET: JHUTZ@DRYCAS
>> Apple // Forever!!! <<