Utilizando el PPI 8255 y el PIT 8253 para reproducir sonido a través del Speaker en el IBM PC

Utilizando el PPI 8255 y el PIT 8253 para reproducir sonido a través del Speaker en el IBM PC

En este post continuamos con las bondades del integrado 8255, que es el interfaz de periferico programable y el Timer de intervalos programables 8253.  El interés es aprovechar el post anterior y mostrarles que el diseño realizado con integrados simulado en Proteus, es igual de válido en las computadoras del IBM PC y Compatibles, que poseen una configuración similar a las que he mostrado. Para ello primero se dará una pincelada de los integrados que intervienen y luego les dejaré un programa en ensamblador para que se pueda entender como se realiza estas acciones en una computadora activando el uso de speaker. Sin más aquí se inicia el tema.

Lo primero es conocer como estan integrados estos chips del 8255 y el 8253 en el diagrama simplificado en el modelo original del IBM PC.

Si se remite al post anterior, encontrará que a la salida del puerto A está conectado el DAC,  Aquí se utiliza el puerto B y el Puerto C.  Especificamente al PB1 que va conectada con una compuerta lógica AND con la Salida de PB0 procesada a traves del integrado 8253 que proporciona el control del Timer. En conjunto el PB0 y PB1 a nivel de software se envia o recibe a través del puerto 61 hex. El integrado generador de clock de la IBM PC es el 8242 y tiene un cristal con una frecuencia de 14,31818 MHz que es divida entre 3 para el intel 8086 y para el integrado 8253 es divida entre 12, como se puede observar al PIT 8253 le ingresa un clock de 1,193 MHz.  Como puede ver el diagrama de bloques posee además un Driver de colector y filtro pasa bajos. Posee una salida del Speaker por lo que su calidad no fue comparada a salidas en Stereo como poseian otras computadoras en su época, si se pregunta porque triunfó en el mecado merece una buena reflexión :). Por el PB1 se transmite el dato que representa la frecuencia y por el PB0 el retardo que debe poseer.

El Integrado del Open Collector Driver es el 75477, recuerde que todos estos chips tienen compatibilidad de 5 voltios TTL.  En la imagen siguiente se muestra la variante del PIT para los modelos AT.

Para terminar, les dejo el assembler del 8086 para operar sobre el Speaker. 

 

LA REFERENCIA ES EL IBM PC EN SU VERSIÓN ORIGINAL.

+----------------------------------------------------------------------------+
!          The - INs ORs ANDs OUTs - of creating sound on the IBM PC         !
!                                                                            !
!        by  William Cravener  520 N. Stateline Rd.  Sharon, Pa. 16146       !
!                                                                            !
!         ¯-Swift-Ware->      Copyright 1991-93       CIS: 72230,1306        
!
+----------------------------------------------------------------------------+

        There are two important electronic chips involved in creating sound 
on the IBM PC - the 8253 timer chip (channel 2 of this chip is connected to 
the speaker),  and the 8255 peripheral interface chip  (it appears regardless
of what peripheral interface chip is used in any particular machine, the same
port address and bit assignments are used).  The pulse rate of each chip can
be altered,  and by combining the actions of the two chips it is possible to
produce special sound effects.

        To make sounds on the IBM PC you must actually turn ON and OFF an
electronic "gate" (which is a kind of toggle switch).  Each time we toggle the 
"gate" ON and OFF again, we create a pulse: a brief period when current flows 
in a circuit (look at the example below).  These pulses are amplified and sent 
to the speaker, where they make a sound.  This "gate" is turned ON and OFF 
with the assembly OUT instruction.


         One
        Pulse
       |     |
 +     +-----+     +-----+     +-----+
       !     !     !     !     !     !
 0 ----+     +-----+     +-----+     +----  <-- Wave form sent to the Speaker
.
       |     |
       |   "gate"
       |    is turned OFF here
     "gate"
      is turned ON here


        The faster we send the pulses, the higher the pitch of the sound. We 
can control how fast we send the pulses by putting a delay loop into our
program.  We then turn the "gate" ON, delay, turn the "gate" OFF, delay, and 
so on and so on. The assembly LOOP instruction is used to cause the delay that
we will need for our example sound program.

        But, before we go on to the example program lets talk a little about 
addressing the PORTs (I/O Ports).  Ports are something like registers, in
that you can send 8-bit or 16-bit data to them. This is always accomplished
using the AL or AX register, you can also read the port contents back into 
the AL or AX register. The big difference between ports and registers is that
ports can be connected to devices either inside or outside of your computer.

        How then, do you access these I/O Ports???    Well, its not that 
difficult once you acquire a little understanding about how to send information 
to these ports using a few very simple assembly language instructions.

        The two most important instructions you will be using are the assembly
IN and OUT instructions. The IN instruction places a byte of information into
the AL or AX register, the OUT instruction copies a byte or word of information
from the AL or AX register. 

The instruction that turns our "gate" ON and OFF is:


OUT     61H, AL    


This instruction copies the contents of the AL register to the port 61H.

        This port addresses the 8255 or equivalent programmable peripheral
interface chip or PPI.  The PPI is used to control the keyboard, the speaker
and the computer configuration settings.

        OUT is very much like the assembly MOV instruction, but instead of
moving information to a register we copy it from a register to a port address
as in the above example (port address 61H).

        Now in the case of creating sound we need to be concerned with two of
the 8-bits we send to port address 61H.  These are the bits numbered 0 and 1.
 
               8-bit number -->  11111111
The two we are interested in ->  111111XX
(marked as X's)                        ||___ bit number 0
                                       |____ bit number 1

        In order to change bits 0 and 1 (without changing the other 6 bits),
we need to find out how all the bits are initially set.  This is easily done 
by using the assembly IN instruction to retreive this value. Once we know how
all 8-bits are initially set, we can change the first two (0 and 1) then copy
the value back to the port address 61H.


IN      AL, 61H    
 

This instruction copies the current 8-bit value of port 61H to the AL register.

        Once we have this 8-bit value we need to change bits 0 and 1 so we
can send the changed ON or OFF value back OUT to our port address.  This is a
two part procedure, first we wish to turn the speaker ON so we OR the 8-bit
value with a value of our own that will not change the upper 6-bits, the 
assembly OR instruction accomplishes this:


OR      AL, 00000011B    ;<- More often then not programmers show 
                    |    ;   this OR or AND value as a binary number.
                    |
                    |____ The letter "B" simply tells the assembler
                          that this group of numbers is a binary value.


The unknown value we get from port 61H ---> 101010 00 <- ( IN  AL, 61H )
 
Then we first OR it with this value ------> 000000 11 <-Our ORing ON value
 -
                                                        this value will enable
                                                        the speaker.

Leaves all bits except 0 and 1 unchanged -> 101010 11 <-The resulting valu
e -
                                                   ||   bits 0 and 1 have both
                                            bit 1__||   been forced to values
                                            bit 0___|   of - 1  (ON)


        Now we want to return this altered number back OUT to port 61H to 
turn ON the speaker. This is easily accomplished by using the above explained
assembly OUT instruction in the following manner.


OUT     61H, AL    ;<-- copy the value in the AL register to Port 61H


        At this point the computers speaker will sound until a new binary 
value is sent back OUT to port 61H to turn the speaker OFF.

Here is the complete code to turn ON the speaker:


IN      AL, 61H          ;Get current value of port 61H.
OR      AL, 00000011B    ;OR AL to this value, forcing first two bits high.
OUT     61H, AL          ;Copy it to port 61H of the PPI chip.


        Here is where our next assembly instruction needs to enter the picture
to turn the speaker OFF. That instruction is the AND instruction, kind of like
the opposite of the OR instruction. As with turning ON the speaker we must use
a similar procedure to turn the speaker OFF.

First get unknown value from port 61H ----> 101010 11 <- ( IN  AL, 61H )
 
Then we first AND it with this value -----> 111111 00 <-Our ANDing OFF val
ue -
(This 8-bit number is the exact opposite                this value will disable
of our OR value above).                                 the speaker.

Leaves all bits except 0 and 1 unchanged -> 101010 00 <-The resulting valu
e -
                                                   ||   bits 0 and 1 have both
                                            bit 1__||   been forced to values
                                            bit 0___|   of - 0  (OFF)

Here is the complete code to turn OFF the speaker:


IN      AL,61H          ;Get current value of port 61H.
AND     AL,11111100B    ;AND AL to this value, forcing first two bits low.
OUT     61H,AL          ;Copy it to port 61H of the PPI chip.


Ok, now if you think about it if we were to turn the speaker ON with:

IN      AL, 61H
OR      AL, 00000011B
OUT     61H, AL

And then, directly turn the speaker back OFF with:

IN      AL, 61H
AND     AL, 11111100B
OUT     61H, AL

        You wouldn't hear a thing (except maybe a click), it all happens to
fast.  We need to cause some kind of delay between the two procedures. We do
this by setting up a LOOP instruction between our two procedures.  This is
done by putting a value in the CX register and executing the assembly LOOP 
instruction.

Here is an example of its use:

MOV     CX, 100          ;Repeat the loop 100 times
DELAY_LOOP:              ;We loop back to here
LOOP    DELAY_LOOP       ;Jump repeatedly to DELAY_LOOP until CX = 0

This will sound the speaker for a Duration of 100 repeated Loops.

Here is the Whole Noisy Routine:


IN      AL,61H          ;Get current value of port 61H.
OR      AL,00000011B    ;OR AL to this value, forcing first two bits high.
OUT     61H,AL          ;Copy it to port 61H of the PPI chip.

MOV     CX,100          ;Repeat the loop 100 times
DELAY_LOOP:             ;We loop back to here
LOOP    DELAY_LOOP      ;Jump repeatedly to DELAY_LOOP until CX = 0

IN      AL,61H          ;Get current value of port 61H.
AND     AL,11111100B    ;AND AL to this value, forcing first two bits low.
OUT     61H,AL          ;Copy it to port 61H of the PPI chip.


        This is a very good method of creating beeps and boops, but we what 
to get a little more involved then this and create more interesting sound
effects. We could create many different sounds if we were to include help
from the computers timer chip. This is the 8253 programmable timer and has
the ability to enable a certain action at a certain point in time. It senses 
timing from oscillations it recieves from the PC's 8284 oscillator chip, which
generates 1,193,180 pulses per second.  The 8253 chip can then be instructed 
how many of these pulses it should wait for before triggering a certain action.
In the case of tone generation, this action consists of sending a pulse to the
speaker.  Before executing this action, the 8253 chip must be programmed for a
particular frequency it should generate.

        There are actually three different timers built into the computer.
Timer 0 is used in DMA data transfer (Direct Memory Access), Timer 1 is used
as a system clock oscillator (18.2 times per second), and the one we are
interested in Timer 2 which is connected to the computers speaker.

        Using the Timer to generate sound is a little more complicated than 
simply sending pulses to the speaker. There are three steps envolved in using
this method of sound creation. 
    
    Step 1.  Copy a certain number to Timer 2 to initialize it.
    Step 2.  Copy a 16 bit number to Timer 2 to establish the frequency 
             of the tone to be generated.
    Step 3.  Turn on the speaker to enable the frequency adjusted sound
             to be heard.

        You access Timer 2 thru two port addresses,  the first is used to 
initialize (make it ready to receive data) thru port 43H, you then send a 
16-bit value in two 8-bit steps.  First, the Least Significant Byte (LSB)
is copied to port address 42H, second, the Most Significant Byte (MSB) is
copied to port address 42H. A 16-bit value is called a WORD, a WORD value
is made up of two BYTES, LSB and MSB.

                         _______________ ____ (WORD)
                        |               |
16-bit binary value ->  00000000 00000001
                        |      | |______|____ (BYTE) LSB
                        |      |         
                        |______|_____________ (BYTE) MSB


Here is how all this is accomplished:

MOV     BX, 1            ; Frequency Value.
                         ; Formula = 1,193,180 \ frequency value
                         ; Will put it in BX for now. 
                         ; The lower the value the higher
                         ; the sound / the higher the value
                         ; the lower the sound.

MOV     AL, 10110110B    ; The Magic Number (use this binary number only!)
OUT     43H, AL          ; Send it to the initializing port 43H Timer 2.

MOV     AX, BX           ; Move our Frequency Value into AX.

OUT     42H, AL          ; Send LSB to port 42H.
MOV     AL, AH           ; Move MSB into AL
OUT     42H, AL          ; Send MSB to port 42H.


IN      AL, 61H          ; Get current value of port 61H.
OR      AL, 00000011B    ; OR AL to this value, forcing first two bits high.
OUT     61H, AL          ; Copy it to port 61H of the PPI Chip
                         ; to turn ON the speaker.

MOV     CX, 100          ; Repeat the loop 100 times.
DELAY_LOOP:              ; We loop back to here.
LOOP    DELAY_LOOP       ; Jump repeatedly to DELAY_LOOP until CX = 0

IN      AL, 61H          ; Get current value of port 61H.
AND     AL, 11111100B    ; AND AL to this value, forcing first two bits low.
OUT     61H, AL          ; Copy it to port 61H of the PPI Chip
                         ; to turn OFF the speaker.


        Next we need to make our sound maker more interesting. To do this 
we will simply use a method of repeating the whole thing a specified number
of times and also increment the frequency value to create a sound that drops
in frequency. To accomplish this we will use the assembly JMP instruction 
and also at the same time, increment our frequency value.
 
Here is a complete example:


MOV     DX,2000          ; Number of times to repeat whole routine.

MOV     BX,1             ; Frequency value.

MOV     AL, 10110110B    ; The Magic Number (use this binary number only)
OUT     43H, AL          ; Send it to the initializing port 43H Timer 2.

NEXT_FREQUENCY:          ; This is were we will jump back to 2000 times.

MOV     AX, BX           ; Move our Frequency value into AX.

OUT     42H, AL          ; Send LSB to port 42H.
MOV     AL, AH           ; Move MSB into AL  
OUT     42H, AL          ; Send MSB to port 42H.

IN      AL, 61H          ; Get current value of port 61H.
OR      AL, 00000011B    ; OR AL to this value, forcing first two bits high.
OUT     61H, AL          ; Copy it to port 61H of the PPI Chip
                         ; to turn ON the speaker.

MOV     CX, 100          ; Repeat loop 100 times
DELAY_LOOP:              ; Here is where we loop back too.
LOOP    DELAY_LOOP       ; Jump repeatedly to DELAY_LOOP until CX = 0


INC     BX               ; Incrementing the value of BX lowers 
                         ; the frequency each time we repeat the
                         ; whole routine

DEC     DX               ; Decrement repeat routine count

CMP     DX, 0            ; Is DX (repeat count) = to 0
JNZ     NEXT_FREQUENCY   ; If not jump to NEXT_FREQUENCY
                         ; and do whole routine again.

                         ; Else DX = 0 time to turn speaker OFF

IN      AL,61H           ; Get current value of port 61H.
AND     AL,11111100B     ; AND AL to this value, forcing first two bits low.
OUT     61H,AL           ; Copy it to port 61H of the PPI Chip
                         ; to turn OFF the speaker.


In conclusion, with the included examples and a little imagination, there is no
limit to the sound effects that are possible to create.

Have Fun !! 

================================================================================

 

 

571total visits,1visits today

ArabicChinese (Simplified)DutchEnglishFrenchGermanItalianPortugueseRussianSomaliSpanish