PARTE 7: FORMA DE ONDA PERSONALIZADA Y REVISADA

Con el fin de acortar la discusión sobre las formas de onda, la última vez se hicieron algunas generalizaciones. Volvamos atrás y maticemos esos comentarios.


Esta es la verdad: las formas de onda personalizadas se pueden usar simultáneamente con otras rutinas. Es más, incluso pueden convivir con rutinas BASIC. ¿Sorprendido? Repasemos los argumentos en contra del uso simultáneo de formas de onda personalizadas.


(1) «BASIC es demasiado lento para cambiar los bits del control de volumen a una frecuencia utilizable». Bien. Se puede hacer muy poco con respecto a la velocidad a la que se ejecuta BASIC.

(2) «La única forma en que BASIC puede ejecutarse simultáneamente con una rutina de lenguaje de máquina es mediante el uso de interrupciones». Hasta donde sabemos, eso también es correcto.

(3) «Las VBI (Vertical Blank Interrupt – Interrupcion de supresión vertical) funcionan a una frecuencia demasiado baja (a intervalos de un sexagésimo de segundo). La frecuencia más alta que se puede obtener a través de VBI sería una onda cuadrada de 30 Hz». También es cierto.

Teniendo en cuenta esto, sería fácil concluir que no hay manera de producir una forma de onda personalizada utilizable que continúe reproduciéndose durante la ejecución de un programa BASIC. Sin embargo, donde esta línea de pensamiento se desvía es en el supuesto de que la única interrupción que tenemos a nuestra disposición es el espacio en «vertical blank – supresión vertical». Es un error comprensible: las rutinas VB1 se han vuelto tan populares que los programadores ahora cuelgan la mitad de sus códigos en ellas, y una vez que descubrimos un enfoque útil para un problema tendemos a pensar en todos los problemas similares de la misma manera. Sin embargo, hay muchas otras interrupciones disponibles, y una en particular que es tremendamente más flexible que una VBI.


Los Temporizadores De Interrupción Del Pokey. El mismo hardware utilizado para generar efectos de sonido estándar del Atari tiene un truco interesante: cuando los temporizadores Pokey 1, 2 y 4 cuentan regresivamente hasta cero, generan una solicitud de interrupción, lo que hace que el 6502 salte a través de los vectores RAM globales VTIMR1, VTIMR2 o VTIMR4. Las direcciones de estos vectores son $210, $212 y $214 respectivamente. Por lo general, estos vectores simplemente apuntan a una secuencia PLA-RTI, por lo que no sucede nada como resultado de la interrupción.


Sin embargo, cuando uno de estos vectores se cambia para que apunte a una rutina de interrupción, nos proporciona una ingeniosa interrupción controlable por frecuencia para rutinas en las que el tiempo es crítico. Las viejas fórmulas para determinar la frecuencia aún se aplican, por lo que todo lo que tenemos que hacer es determinar con qué frecuencia queremos que se ejecute la rutina, calcular el valor AUDF correspondiente e introducirlo en los registros de frecuencia para ese canal en particular. Ni siquiera tendremos que preocuparnos por recargar el temporizador, Pokey lo recarga automáticamente con el último valor introducido en AUDF.


A veces, la capacidad incorporada en esta máquina simplemente te deja sin aliento.


Generar formas de onda personalizadas simultáneas se vuelve terriblemente fácil cuando se ve desde esta perspectiva. Necesitamos tres rutinas: una para configurar la interrupción (iniciar el sonido), otra para borrar la interrupción (hacer que se calle) y la interrupción en sí, que simplemente seleccionará los valores sucesivos de una tabla de formas de onda y los introducirá en AUDC. Una vez que se ha ejecutado la rutina de configuración, BASIC selecciona la frecuencia de la nota y la introduce en AUDF de la misma manera que hemos estado seleccionando frecuencias todo el tiempo. BASIC puede elegir una nota, irse y hacer algo interesante (El programa de ejemplo dibuja algunos cuadros bonitos) y el sonido no se detendrá hasta que ejecutemos la rutina de silencio.


¿Las limitaciones? Bueno, hay tres. Cuanto mayor sea la frecuencia, más notable será la distorsión causada por DMA, etc. Aún más alto, las interrupciones ocurren tan rápido que la máquina no puede prestar atención a nada más y bloquea el programa en el valor AUDF 2. (Puede recuperarlo presionando la tecla SYSTEM RESET y su programa seguirá intacto).


La tercera limitación es que cuanto mayor sea su frecuencia, menos tiempo de máquina estará disponible para el resto del programa. Por ejemplo, usar el editor de pantalla mientras la interrupción avanza con un valor AUDF 3 es extraño: el sistema operativo se vuelve tan lento que puede ver cada línea individual desplazarse hacia arriba en la pantalla. Evidentemente, este efecto sería bastante inaceptable en un programa.


El Programa De Ejemplo. La demostración BASIC instala las tres rutinas que acabamos de describir y luego las utiliza para reproducir un motivo aplastado de la «Sonata Claro de Luna» de Beethoven mientras dibuja cuadros en la pantalla. Las variaciones de tempo son estrictamente el resultado de los distintos períodos de tiempo necesarios para dibujar los cuadros de diferentes tamaños; ciertamente es posible lograr un tempo constante alterando la rutina de visualización a una de una duración más predecible.


La forma de onda que se reproduce es una onda de rampa (o sierra), que produce un tono nasal bastante diferente al de la onda cuadrada estándar y, sin embargo, lo suficientemente agradable como para usarlo como efecto musical. Las frecuencias utilizadas son bastante bajas, para evitar los problemas descritos anteriormente, pero se pueden utilizar frecuencias más altas que éstas.


Ambos listadoss deberían explicarse por sí solos, pero dos elementos merecen un comentario. Tenga en cuenta que la rutina BASIC tiene cuidado de introducir un valor de frecuencia en AUDF antes de llamar a la rutina de configuración. Esto es para garantizar que AUDF contenga un valor lo suficientemente bajo como para evitar el bloqueo del programa.


También tenga en consideración que la tabla de formas de onda (en el listado Ensamblador) tiene ocho pasos. Acortar o alargar esta tabla aumentará o disminuirá las frecuencias obtenidas por AUDF. Acortar la tabla a cuatro pasos, por ejemplo, produciría sonidos una octava más altos que los creados por la versión actual. Esta es una forma de conseguir tonos más altos sin que el resto del programa se vuelva lento, a expensas de la resolución de la forma de onda. Si cambia la longitud de la tabla, recuerde cambiar la parte del código que envuelve el puntero WINDX de la forma de onda.


Ingrese este programa, use las rutinas en su propio trabajo y esperamos que disfrute tanto usándolas como lo hizo su corresponsal al escribirlas. Esta técnica, y las posibilidades que abre, es uno de esos descubrimientos fortuitos sobre Atari que pueden dejarte emocionado durante días.


Demostración BASIC De Sonido Usando Una Interrupción

0001 REM Interrupt Sound Demo
0002 REM (with apologies to Ludwig)
0003 REM Routine addresses and freq register equate
0004 SET=1536:CLEAR=1558:AUDF=53760
0005 REM Poke in machine language
0006 FOR L=1536 TO 1600
0007    READ BYTE
0008    POKE L,BYTE
0009 NEXT L
0010 REM Data bug check
011 READ BYTE
0012 IF BYTE <>-1 THEN ?"Data error.":STOP
0013 REM Set up graphics
0014 GRAPHICS 23
0015 REM Initialize freq first!
0016 POKE AUDF,127
0017 REM Start interrupt
0018 Q=USR(SET)
0019 REM Our first beat
0020 FOR D=1 TO 100:NEXT D
0021 REM Play melody
0022 BYTE=95
0023 POKE AUDF,BYTE
0024 C=C+1:IF C>3 THEN C=0
0025 X=X+7:IF X >80 THEN X=X-80
0026 Y=Y+1:IF Y>48 THEN Y=0
0027 COLOR C
0028 PLOT X,Y:DRAWTO 159—X,Y
0029 DRAWTO 159—X,95—Y:DRAWTO X,95-Y
0030 DRAWTO X,Y
0031 READ BYTE
0032 IF BYTE<> —1 THEN 0023
0033 REM Turn of interrupt
0034 Q=USR(CLEAR)
0035 REM Wait for key press
0036 IF PEEK(764)=255 THEN 0036
0037 END
0038 REM Machine language routines
0039 DATA 120,169,35,141,16,2,169,6
0040 DATA 141,17,2,165,16,9,1,133,16
0041 DATA 141,14,210,208,10,120,165
0042 DATA 16,41,254,133,16,141,14
0043 DATA 210,88,104,96,138,72,174
0044 DATA 57,6,189,58,6,141,1,210
0045 DATA 232,138,41,7,141,57,6,104
0046 DATA 170,104,64,16,18,20,24,31
0047 DATA 16,16,16,-1
0046 REM
0049 REM Melody data
0050 DATA 80,127,95,80,120,95
0051 DATA 80,120,95,80,120,90,71,120
0052 DATA 90,71,127,101,71,127,95
0053 DATA 80,127,95,85,143,101,85
0054 DATA 161,127,95,161,127,161
0055 DATA 192,192,192,-1	

Rutina En Lenguaje Ensamblador De Sonido Usando Una Interrupción


TITLE 'Interrupt Snd Demo'
;OS equates
IRQEN = $D20E ;IRQ enable
POKMSK = $10 ;shadow for IRQEN
AUDF = $D200 ;freq register
AUDC = $D201 ;volume register
VTIMR1 = $210 ;timer vector
;
ORG $600
;Set and Clear are to turn
;the sound routine on and off
SET    SEI
LDA #LOW TIMRI ;point to
STA VTIMR1 ;sound
LDA #HIGH TIMR1 ;routine
STA VTIMR1+1
LDA POKMSK ;enable it
ORA #1
STA POKMSK
STA IRQEN
BNE SET2
CLEAR SEI
LDA POKMSK ;kill rout
AND #$FE
STA POKMSK
STA IRQEN
SET2    CLI
PLA ;remove args
RTS ;back to Basic
;
;here's the interrupt sound routine
TIMRI    TXA ;save X
PHA
LDX WINDX ;get wave X
LDA WAVE,X ;get audc value
STA AUDC ;& place it
INX ;next step
TXA ;do wraparound
AND #7
STA WINDX
PLA ;restore X
TAX
PLA
RTI
;
WINDX    DS 1    ;wave index
;waveform table
WAVE    DB $10,$12,$14,$18
DB    $1F,$10,$10,$0
END	

Leer la siguiente columna que es modulación por ancho de pulso.



Publicado en revista Softline Volumen 2 de Julio y Agosto del 1983, páginas 19 al 20.