CS-220, Sec. 90, Week 10-A
R. Eckert


In the last set of notes we saw that a musical tone of frequency ftone
could be produced on a PC by outputting alternating 1's and 0's to the
bit that controls the PC's speaker (bit-1, port 61h). But we needed to
program a delay between these pulses using the delay loop:

         top:   loop   top

The number of iterations of the loop was determined (for a Pentium
running at fclk Mz) by:

         N = fclk/(12*ftone)

Unfortunately, this equation only works for a PC with a Pentium, and we
need to know the frequency of the system clock to use it.

A better way to determine the iteration count needed for a given delay is
to use the fact that on ALL PCs and PC-compatibles (regardless of the
processor used or the frequency of the system clock), the Operating
System makes bit-4 of input port 61h toggle every 15.085 microseconds. So
to achieve a delay of t (the time for one pulse of the sound wave), we 
could determine the number of 15.085 microsecond intervals in t:

       num_ints = t/(15*10-6)

       But t is one-half the period of a sound wave of frequency ftone
       t = 1 / (2*ftone)
       So num_ints = 1 / (2 * 15*10-6 * ftone)
       Or after simplifying: num_ints = 33145/ftone

We can then execute the following pseudo-code to implement the t delay:

       Do num_ints times
               AGAIN:  Input from port 61h
                       Test bit-4 for a change
                       J_nochange AGAIN

To make our sound wave last for a duration T, all we need to do is
compute the number of pulses that would fill that time interval. That
number would be:

       num_pulses = T/t

But, as we have seen, the duration t of a pulse is:

       t = 1/(2*ftone)
       So num_pulses = T / (1/2*ftone)
       Or num_pulses = 2*T*ftone

So our algorithm for outputting a sound wave of frequency ftone for a
duration T would be:

1. Compute number of 15 microsecond intervals for the tone: 
      num_ints = 33145/ftone

2. Compute number of pulses required for interval T      num_pulses = 2*T*ftone

3. Execute the following pseudo-code:
     Input from port 61h
     Turn off bit-0 without changing other bits
     Repeat num_pulses times
        Toggle bit-1 of AL
        Output to port 61h
        Delay for t (see above)