Аппаратное обеспечение персонального компьютера

Программа IOSOUND


Приведем исходный текст программы IOSOUND, генерирующую звук без использования таймера (листинг 5.3.). Эта программа формирует импульсы при помощи манипуляций с разрядом 1 порта 61h.

Листинг 5.3. Файл iosound\iosound.с

// =====================================================

// Генерация звукового сигнала через порты таймера

//

// (C) Фролов А.В, 1997

//

// E-mail: frolov@glas.apc.org

// WWW:    http://www.glasnet.ru/~frolov

//            или

//         http://www.dials.ccas.ru/frolov

// =====================================================

#include <stdio.h>



#include <conio.h>

#include <dos.h>

#define FREQUENCY 200

#define CYCLES 30000

int main(void)

{

  // Во время генерации звука прерывания должны

  // быть запрещены.

  _disable();

  _asm

  {

    // Загружаем количество циклов - периодов

    // генерируемых импульсов

    mov   dx, CYCLES

    // Отключаем громкоговоритель от таймера

    in    al, 61h

    and   al, 0feh

    // Цикл формирования периода

sound_cycle:

    // Формируем первый полупериод, подаем

    // на громкоговоритель уровень 1

    or    al, 2

    out   61h, al

    // Формируем задержку

    mov   cx, FREQUENCY

first: loop  first

    // Формируем второй полупериод, подаем

    // на громкоговоритель уровень 0

    and   al,  0fdh

    out   61h, al

    // Формируем задержку

    mov   cx, FREQUENCY

second: loop  second

    // Если сформированы не все периоды, переходим

    // к формированию следующего периода.

    dec   dx

    jnz   sound_cycle

  }

  // Разрешаем прерывания

  _enable();

  // Выключаем громкоговоритель

  outp(0x61, inp(0x61) & 0xfc);

 

  return 0;

}

Так как в программе IOSOUND для формирования полупериодов используется задержка с помощью команды LOOP, высота генерируемого тона будет зависеть от производительности системы.

Такой зависимости можно избежать, если перед началом работы измерять производительность и соответствующим образом корректировать константу, загружаемую в регистр CX перед вызовом команды LOOP. Измерение производительности лучше всего выполнять с помощью таймера, определяя время выполнения команды LOOP.



Содержание раздела