Справочник программиста на персональном компьютере фирмы IBM. Таймеры и звук - Одновременная генерация разных звуков

ОГЛАВЛЕНИЕ

     2.2.9 Одновременная генерация разных звуков.


   Только микросхема генератора  звука,  имеющаяся в PCjr, позво-
ляет  одновременно генерировать разные звуки (см.   обсуждение  в
[2.2.1]). Однако ассемблер позволяет объединить два способа гене-
рации  звука,  что создает имитацию одновременной генерации  двух
разных звуков.  Интерференция этих двух сигналов приводит к слож-
ной  форме звуковой волны.  Каждый из двух звуков  имеет  меньшую
громкость, поэтому в результате  получается  скорее жужжание, чем
два разных голоса. Этот прием реально полезен только для создания
звуковых эффектов.

   Низкий уровень.


   Надо просто объединить два метода  генерации звука, показанные
в [2.2.2] и [2.2.3]. Начните звук через канал 2 микросхемы тайме-
ра.  Затем модулируйте  выход  динамика,  за  счет бита 1 порта B
микросхемы  интерфейса с периферией.  Второе действие  определяет
продолжительность звука. Не забудьте выключить микросхему таймера
при завершении.

;---начинаем генерацию звука через канал 2 таймера
      IN   AL,61H          ;получаем байт из порта B
      OR   AL,3            ;устанавливаем младшие два байта
      OUT  61H,AL          ;посылаем байт обратно
      MOV  AL,10110110B    ;цепочка для командного регистра 8253
      OUT  43H,AL          ;посылаем в регистр
      MOV  AX,600H         ;счетчик для канала 2
      OUT  42H,AL          ;посылаем младший байт
      MOV  AL,AH           ;готовим старший байт
      OUT  42H,AL          ;посылаем старший байт
;---генерируем вторую частоту микросхемой 8255
NUMBER_CYCLES  EQU  9000           ;число переключений
FREQUENCY      EQU  150            ;задержка для половины цикла
               CLI                 ;запрет прерываний
               MOV  DX,NUMBER_CYCLES  ;DX считает длину тона
               IN   AL,61H         ;получаем статус порта
               AND  AL,11111111B   ;отключаем динамик от таймера
NEXT_CYCLE:    OR   AL,00000010B   ;включаем динамик
               OUT  61H,AL         ;посылаем назад в порт
               MOV  CX,FREQUENCY   ;задержка на 1/2 цикла
FIRST_HALF:    LOOP FIRST_HALF     ;
               AND  AL,11111101B   ;выключаем динамик
               OUT  61H,AL         ;посылаем команду в порт
               MOV  CX,FREQUENCY   ;задержка на 1/2 цикла
SECOND_HALF:   LOOP SECOND_HALF    ;
               DEC  DX             ;меняем счетчик циклов
               JNZ  NEXT_CYCLE     ;если 0, то пора кончать
               STI                 ;разрешаем прерывания
;---выключение канала 2 микросхемы таймера
               IN   AL,61H         ;получаем статус порта
               AND  AL,11111100B   ;сбрасываем 2 младших бита
               OUT  61H,AL         ;посылаем байт обратно