Справочник программиста на персональном компьютере фирмы 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 ;посылаем байт обратно