The Intel 8253/8254 Programmable Interval Timer and Sound on a PC

The 8254 PIT has three internal timer/oscillator channels (timer 0, timer 1, 
and timer 2) which can be programmed to output six different types of signals 
related to a "count time" that has been loaded into the latch associated with 
each timer/oscilator when it is programmed. The three latches associated with 
each of the 8254 timers are mapped to ports 40h, 41h, and 42h on an IBM-PC 
compatible computer. The 8254 has a fourth internal "command" register that is 
used to program the chip and that is mapped to port 43h on an IBM-PC.

Command register format:
           |  7 | 6 | 5 | 4 | 3 | 2 | 1 | 0  |
              |   |   |   |   |   |   |   |__ Count format (0=binary)
              |   |   |   |   |___|___|_______ Mode of operation 
              |   |   |   |                    (3 = 011B = square wave)
              |   |   |__ |_______ How to access latch (11B = LSB then MSB)
              |___|_______________ Timer/oscillator channel

On an IBM-PC timer channel 2 is connected through an AND gate to the computer's 
speaker. The timer starter is connected to Bit-0 of Port 61h. Sending a 1 to that 
bit of that port starts the timer. If the mode had been set to "square wave" 
(mode 3), then a square wave will be sent to one input of the AND gate feeding 
the speaker. (The other input of the AND gate comes from Bit-1 of port 61h.) The 
frequency of the square wave is determined by how the timer has been programmed.

The 8254's timers are programmed by outputing the appropriate command byte to 
its command port (Port 43h on a PC). This command byte will include bits that 
specify the timer to be programmed, its mode of operation, and how its count-time 
latch is to be accessed. Mode 3 indicates that we want a square wave. 
Subsequently, if we wish the specified timer to output a square wave of a given 
frequency, a count value appropriate to that frequency must be sent to that 
timer's latch register. That count value must be computed by dividing the 
frequency of the timer's clock (1.193182 MHz) by the frequency of the desired 
square wave. Since this value will be a word-sized number and since the timer 
latch registers are byte-sized, the  count value must be output to the timer's 
latch one byte at a time, the least significant byte first, then the most 
significant byte. That means that when the command byte was sent, the "how to 
access" bits should have been set to a value of 11B.

After programming timer 2 to output a square wave of a given frequency on a PC, 
the timer is started by outputting a 1 to bit-0 of port 61h (making sure that 
bit-1 of the same port is also set to 1). That will cause the sound to be 
produced by the speaker. To stop the timer (and the sound) a zero should be set 
to bit-0 of port 61h.

The steps required to output a musical note of a given frequency are the 

1. Compute the latch count value from the frequency of the musical note 
2. Output a command byte to port 43h that specifies that timer channel 2 is to 
   be used, the count format, the mode of operation, and how the latch is to be 
3. Output the least significant byte of the latch count value to port 42h
4. Output the most significant byte of the latch count value to port 42h
5. Start the timer by outputting the correct bit pattern to Port 61h
6. Delay while the note plays
7. Stop the timer by outputting the correct bit pattern to Port 61h