Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Objetivos.
• Comprender e implementar las tres técnicas de E/S: mediante programa ("polling" o sondeo),
mediante interrupciones, y mediante DMA ("Direct Memory Access" o acceso directo a memoria).
• Conocer los detalles de programación de una tarjeta de adquisición de datos (en concreto la PC-
LabCard 812PG), o bien de una tarjeta de sonido SoundBlaster.
• Comprender y programar el controlador de DMA 8237.
• Realizar temporizaciones con el circuito 8253.
Enunciado
Realizar tres programas EXE para digitalizar sonido utilizando bien la tarjeta de adquisición de datos PCL-
812PG, bien la SoundBlaster:
• El primero utilizará E/S por programa (fácil, y lenta en un PC lento).
• El segundo usará E/S por interrupciones (ligeramente más compleja, pero más rápida),
• El tercero E/S por DMA (la más compleja de implementar y la más rápida).
Las muestras digitales adquiridas se guardarán en un búfer en memoria y se escribirán en un archivo en
disco en formato WAV. Para ello se utilizará la técnica de "doble búfer" (dos búferes de 8 KB cada uno;
cuando la interrupción o el DMA escribe en uno, se graba el otro en disco).
Opcionalmente, el programa puede reproducir el sonido que se está digitalizando como se hacía en
la práctica de ensamblador “reproducción de sonido”.
Información adicional
El controlador de DMA (DMAC) sólo puede transferir datos dentro de una página física de memoria.
El mapa de memoria está dividido en páginas físicas de 64 KB cada una. Para 1 MB de memoria, está
dividido en 16 páginas como sigue:
Segmento Dirección Segmento:Offset
0 0000:0000 -> 0000:FFFF
1 1000:0000 -> 1000:FFFF
2 2000:0000 -> 2000:FFFF
... ...
E E000:0000 -> E000:EFFF
F F000:0000 -> F000:FFFF
1/7
• La parte final de la página física 6 desde el offset 0xC000 hacia delante.
• El parte inicial de la página 7 hasta el offset 0x1FFF.
El DMAC no puede ser programado para transferir el conjunto de datos de una vez si no están
dentro de la misma página física. En este caso los datos deben ser manejados en 2 bloques. El máximo
número de datos que pueden ser transferidos cada vez es 64 KB.
El contador de datos del DMAC es siempre 1 byte menos que el número real de bytes a transferir.
Así:
Contador_de_datos = número_real_de_datos – 1
Por ejemplo, para transferir un byte de datos, Contador_de_datos = 0. Para transferir 64 KB de datos,
Contador_de_datos = 65535 (0xFFFF).
La dirección la página física se escribe en un puerto de un byte que se encuentra en una de las
siguientes direcciones: 0x87 para el canal 0, 0x83 para el canal 1, 0x81 para el canal 2 y 0x82 para el canal
3.
2/7
Formato WAV:
Bytes Contenido usual Tipo de dato Propósito/Descripción
00 - 03 “RIFF” char [4] Identificador de trozo “RIFF”. El
formato WAVE está compuesto a su
vez por dos trozos: “fmt ” y “data”.
04 - 07 long Tamaño del resto del trozo RIFF
que sigue a este número = 36 +
tamaño de las muestras = tamaño
del archivo en bytes, incluyendo
cabecera, menos 8.
08 - 11 “WAVE” char [4] Identificador de formato del trozo.
12 - 15 “fmt ” char [4] Identificador del trozo “fmt ”.
16 - 19 16 long Tamaño del resto del trozo “fmt “
que sigue a este número.
20 - 21 1 unsigned short Formato de audio. PCM = 1. Valores
distintos de 1 indican algún modo
de compresión.
22 - 23 1 unsigned short Número de canales. 1 = mono, 2 =
estéreo.
24 - 27 long Frecuencia de muestreo
(muestras/segundo) = 8000, 11025,
22050, 44100.
28 - 31 long Número de bytes por segundo =
frecuencia de muestreo * nº de
canales * bits por muestra / 8
32 - 33 1 short Alineamiento de bloque = nº de
bytes para una muestra = nº de
canales * bits por muestra / 8.
34 - 35 8 short Número de bits por muestra (8, 16).
36 - 39 “data” char [4] Identificador del trozo “data”.
40 - 43 long Tamaño del trozo “data” a partir de
este número = nº de bytes
muestreados = nº de muestras * nº
de canales * bits por muestra / 8
44 - Muestras de sonido
Más información sobre el formato WAV en:
http://ccrma-www.stanford.edu/courses/422/projects/WaveFormat/
3/7
Programación de la SoundBlaster
#define BASE 0x220
(*) Lectura del DSP (función sin argumentos que devuelve el dato leído)
(**) Escritura de un dato u orden en el DSP (función con un argumento, que no devuelve nada)
Hay que reiniciar el DSP antes de programarlo. Esto se hace mediante los siguientes pasos:
1) Escribir un 1 en el puerto RESET (BASE + 6)
2) Esperar 3 microsegundos
3) Escribir un 0 en el puerto RESET (BASE + 6)
4) Leer de READ_DATA* hasta obtener el byte “listo” (0xAA)
El DSP tarda normalmente unos 100 µs en reiniciarse. Si tarda más de cierto tiempo razonable (unos
200 µs) es porque ha ocurrido un error (dirección BASE incorrecta o no hay SoundBlaster).
Ejemplo:
unsigned char masterleft=16;
outportb(MixerAddr,MasterLeft);
outportb(MixerData,masterleft<<3);
4/7
Registros/Listado de puertos
Nº de bit
Índice 7 6 5 4 3 2 1 0
0x00 Reset Mixer
0x04 Voice Volume (L) Voice Volume (R)
0x0A . Mic Volume
0x22 Master Volume (L) Master Volume (R)
0x26 MIDI Volume (L) MIDI Volume (R)
0x28 CD Volume (L) CD Volume (R)
0x2E Line Volume (L) Line Volume (R)
0x30 Master Volume (L) .
0x31 Master Volume (R) .
0x32 Voice Volume (L) .
0x33 Voice Volume (R) .
0x34 MIDI Volume (L) .
0x35 MIDI Volume (R) .
0x36 CD Volume (L) .
0x37 CD Volume (R) .
0x38 Line Volume (L) .
0x39 Line Volume (R) .
0x3A Mic Volume .
PC Speaker
0x3B .
Volume
0x3C Output Mixer Switches
. . Line.L Line.R CD.L CD.R Mic
0x3D Input Mixer (L) Switches
. . MIDI.L MIDI.R Line.L Line.R CD.L CD.R Mic
0x3E Input Mixer (R) Switches
. . MIDI.L MIDI.R Line.L Line.R CD.L CD.R Mic
0x3F Input Gain (L) .
0x40 Input Gain (R) .
0x41 Output Gain (L) .
0x42 Output Gain (R) .
0x43 . AGC
0x44 Treble (L) .
0x45 Treble (R) .
0x46 Bass (L) .
0x47 Bass (R) .
1) Disparar conversión enviando la orden 0x20 (conversión A/D directa de 8 bits) al puerto
WRITE_COMMAND_DATA**
2) Leer dato digital del puerto READ_DATA*
5/7
Programa 2: E/S por DMA
Programación del DSP para que envíe a la memoria un bloque de muestras por DMA sin autoinicio
La orden 0x14 permite el envío de muestras desde memoria a la SoundBlaster y el 0x24 la lectura en
memoria desde la tarjeta, ambos usando DMA y 8 bits. El proceso para la captura de muestras es el
siguiente:
1) Programar el DMAC 8237 para la transferencia.
2) Enviar la orden 0x24 al puerto WRITE_COMMAND_DATA** (escritura en memoria por DMA sin
autoinicio)
3) Enviar el número de datos - 1 (2 bytes, el LSB primero) al puerto WRITE_COMMAND_DATA**
4) En la ISR: reprogramar el DMAC, activar una variable que indique que se ha llenado un buffer, y leer el
puerto DATA_AVAILABLE_STATUS (BASE + 0x0E) para reconocer la interrupción.
Programación del DSP para que envíe a la memoria un bloque de muestras por DMA con autoinicio
Para detener las peticiones de DMA (por ejemplo, cuando se pulse una tecla para finalizar) se envía la
orden DMA_STOP (0xD0) al puerto WRITE_COMMAND_DATA**
Más información
http://faculty.petra.ac.id/irwankj/ap2/sb16doc.html
Buscar archivo sbdsp.txt en la web.
http://oxygen.it.net.au/mixing/index.html
http://the.earth.li/~tfm/oldpage/sb_dsp.html
http://www.geocities.com/SiliconValley/Park/8933/sound.html
http://www.inversereality.org/tutorials/sound%20programming/soundblaster16.html
6/7
Programación de la PCL-812PG
#define BASE 0x230
Inicialización de la tarjeta
MSB LSB
0 0 0 0 X X X X Y Y Y Y Y Y Y Y
X X X X Y Y Y Y
(MSB << 4) | (LSB >> 4)
Inicialización de la tarjeta
En las E/S por interrupciones y E/S por DMA es necesario programar el temporizador 8253 de la
tarjeta (distinto del de la placa madre del PC). Se debe programar los contadores 1 y 2 en modo 3:
"Generador de onda cuadrada". Se puede mandar una cuenta 2 al contador 2, con la que la entrada al
contador 1 es 1 MHz exacto y la cuenta a enviar al contador 1 sería 1 MHz / frecuencia_de_muestreo.
Se producirá la interrupción IRQ 7 [INT (7+8) = INT 0x0F] cada vez que esté lista una muestra. Al
final de cada interrupción hay que enviar cualquier dato al puerto BASE+8 (como se ha indicado más arriba,
esto también hay que hacerlo antes de que se haga la primera llamada a la interrupción).
En la E/S por DMA se produce la interrupción IRQ 7 [INT (7+8) = INT 0x0F] cuando termina la operación de
transferencia de un bloque completo (cuando el contador pasa de 0 a 0xFFFF). El canal de DMA es el 3.
7/7