CS-220, Sec. 90, Week 9-C
R. Eckert

TIMING ON COMPUTER SYSTEMS

Frequently microcomputer systems are used to control other equipment. And
in many cases, we need to be able to do things like outputting a voltage
pulse of a specified length. Let us assume that we want to output a pulse
(a one followed by a zero) lasting t seconds to a given bit of a given
output port. The general method would be:

output a 1 to the bit of the port
wait for t seconds
output a 0 to the bit of the port

The question then becomes "how do we wait for T seconds?"

If we set up a delay loop, know how many computer clock cycles are
used in the loop, and know how much time a single clock cycle lasts, we
can adjust the number of iterations of the delay loop so that the time
consumed is equal to the desired pulse length (t). In other words:

t = (total # of clocks used)*(time for 1 cycle)

If we know the frequency of the computer's system clock (fclk), the time
for one clock cycle (tclk) is just the inverse of that frequency.

       tclk = 1/fclk

So our equation becomes:

   t = (total # of clocks) * (1 / fclk) 

And if we know what processor is being used in the computer, we can
consult the specification sheets for that processor and obtain the number
of clock cycles each instruction in its instruction set takes.

As an example, assume we are using a microcomputer with a Pentium
processor that is running at a clock frequency of 50 MHz. We wish to
output a pulse that lasts 1 millisecond to bit 1 of port 23 on this
computer. (Perhaps that bit of that port is connected to a device that
requires the 1 millisecond pulse to start running.)

If we look at the specification sheets for the Pentium, we can get the
following information:

 instruction     number of clocks
 --------------------------------
 mov reg,immed          1
 loop                   6/5 (6 if branch is taken, 5 if not)
 out al,immed           12

Now let's write some code. We'll use the loop instruction to implement
a delay loop. The only problem is that we need to determine how many
iterations will be needed to achieve the 1 millisecond delay. Let us
assume that the number of iterations is N (unknown at this time).

       mov     cx,N         ;Set up for N iterations of the delay loop
       mov     al,00000010b ;Set bit 1
       out     23,al        ;the pulse starts here
again: loop    again        ;repeat N times
       mov     al,00000000b ;Clear bit 1
       out     23,al        ;the pulse ends here

Now let's look at how many clock cycles are taken from the moment the
pulse starts (after the first out instruction executes) until the moment
the pulse ends (after the second out instruction executes:

again: loop    again  -----> 6*(N-1) + 5 clocks   (branch taken N-1 times)
       mov     00000000b --> 1 clock
       out     23,al  -----> 12 clocks

Total # of clocks = 6*(N-1)+5 + 1 + 12
                  = 6*N + 12

Time for one clock = 1/fclk = 1/(50*10^6)

Substituting in the equation above (and realizing that the required delay
is t = 1 millisecond = 1 * 10^-3)

     1*10^-3 = (6*N+12) * 1/(50*10^6)

In all practical cases, 6*N >> 12, so this becomes

     1*10^-3 = 6*N/(50*10^6)

We can easily solve this for N.

The result, for this example, is:

     N = 8333 iterations.

If we use this number for N in the above program fragment, a pulse of the
desired duration will be output.

In general if we are using a processor running at a frequency fclk and
have a loop instruction that takes C clocks for each iteration and repeats
N times, a delay of duration T can be obtained by solving for N in the
following equation:

   t = C*N/fclk


GENERATING SOUND (MUSICAL TONES) WITH THE SPEAKER OF A PC

A sound is nothing more than a wave. The pitch of the sound is determined
by its frequency. We can emulate a sound wave by sending out a square
wave. This is nothing more than an alternating series of 1's and 0's. We
can determine the pitch of the sound by adjusting the delay time between
each 1 and zero. The following diagrams show different square-wave "sound"
signals.
           __________            __________            __________
__________|          |__________|          |__________|          |_______

    ___     ___     ___     ___     ___     ___     ___     ___     ___
___|   |___|   |___|   |___|   |___|   |___|   |___|   |___|   |___|   |_

The second one would have a higher pitch (frequency) than the first.

All IBM-PC compatible computers contain a speaker. The speaker is wired as
shown below:

  Bit-1, Port 61h -----------------> AND ---------> SPEAKER
                                 --> GATE
                                |
  Bit-0, Port 61h ---> Timer/ --
                     Oscillator

We can generate a sound in one of two ways:

1. Set the upper input to the AND gate to 1, set the timer/oscillator to
generate a square wave of the appropriate frequency (this may be done by
outputting the correct information to the timer/oscillator control ports--
ports 40h-43h), and start the timer/oscillator by outputting a 1 to its
input.

2. Turn off the timer/oscillator so that its output is always high (by
outputting a 0 to its input), and send alternating 1's and 0's to the
upper input to the AND gate. The programmed delay between each 1 and 0
will determine the frequency (pitch) of the sound produced.

We will look in detail at method 2. The following pseudo-code could be
used to generate an unending sound.

     Input from Port 61h
     Turn off Bit 0 (without affecting the other bits)
top: Output to Port 61h
     Toggle bit 1 (without affecting the other bits) --> 101010...
     Delay (the duration of the delay loop determines the pitch)
     jmp top

The following is a closeup of one complete sound wave:
     _________________________                           __
  __|                         |_________________________|

    |<------------------------------------------------->|
                              P

P is the period of the sound wave, and this is equal to the inverse of its
frequency. If we want to output a sound wave with a frequency ftone, we
need to output a 1, wait for P/2, then output a 0, wait for P/2, and
repeat the procedure. The delay time of each of these "pulses" is P/2, or,
in other words, 1/(2*ftone).

The code we might use to output an unending sound wave:

        in    al,61h        ;get contents of port
        and   al,11111110b  ;turn off bit 0
top:    out   61h,al        ;next pulse (half wave)
        mov   cx,N          ;N depends on fclk and ftone
delay:  loop  delay         ;delay proper amount of time
        xor   al,00000010b  ;toggle bit 1
        jmp   top           ;do it again

The value of N will determine the frequency of the sound.

Using the same equation we used at the beginning of this unit and
assuming that the processor is a pentium, we have for the delay:

   t = 6*N/fclk

But, the required delay t = P/2 = 1/(2*ftone).

Substituting this, and solving for N, we get:

   N = fclk/(12*ftone)

If, for example, we wanted to output a "middle-C" (ftone = 264 Hz) on a PC
running at 50 MHz (fclk = 50000000) with a Pentium processor, the equation 
gives N = 15783.