8.2. Динамик

Внутри корпуса IBM PC есть маленький динамик. Программа может управлять звуками, генерируемыми этими динамиком. Для этого нужно управлять некоторыми выходными битами микросхемы 8255 и генератора тона в микросхеме 8253.

На Фиг. 8.1 показана программа, которая управляет динамиком двумя разными способами. Первый способ, помеченный в листинге меткой DIRECT, непосредственно управляет динамиком. Бит 1 выводного порта 61H подключен к динамику. Всякий раз, когда программа меняет значение этого бита, диффузор динамика двигается либо наружу, либо внутрь. Быстро меняя значение этого бита, программа генерирует звук. Это иллюстрирует первая часть программы на Фиг. 8.1, она меняет значение бита 1, порождая высокочастотный тон. Скорость, с которой программа меняет бит 1, определяет частоту тона. Взяв на себя непосредственное управление динамиком, вы должны прежде всего работать с выводным портом микросхемы 8255 системной платы. Программируемый периферийный интерфейс микросхемы 8255 (PPI) имеет всего три входных или выходных, порта. IBM PC инициализирует микросхему 8255 так, чтобы получилось два входных порта - 60H и 62H - и один порт вывода, 61H. Порт 60H в первую очередь вводит значения с клавиатуры. Его можно также использовать для чтения положения переключателей на системной плате. Обычно состояния этих переключателей читаются только один раз, во время инициализации при включении питания системы. Результат программа BIOS записывает в память для дальнейшего использования. Поэтому с точки зрения наших целей можно считать, что порт 60H непосредственно обслуживает ввод с клавиатуры. Вообще входной порт выполняет важную функцию. Он служит буфером между микропроцессором и устройством ввода-вывода; он передает данные микропроцессору только тогда, когда последний запрашивает их командой IN. Все остальное время вводной порт задерживает данные и не допускает, чтобы они повлияли на работу микропроцессора.


Microsoft (R) Macro Assembler Version 5.00                  1/1/80 04:03:56
Фиг. 8.1 Управление динамиком                                     Page  1-1
PAGE  ,132
                         TITLE    Фиг. 8.1 Управление динамиком

0000                     STACK    SEGMENT STACK
0000    0040[                     DW        64 DUP (?)
             ????
            ]
0080                     STACK    ENDS

0000                     CODE     SEGMENT

                                  ASSUME    CS:CODE
0000                     SPEAKER  PROC      FAR
0000    1E                        PUSH      DS        ; Адрес возврата
0001    B8 0000                   MOV      AX, 0
0004    50                        PUSH     AX
                         ;-----        Задание режима работы динамика
0005    2B C9                     SUB      CX, CX     ; Счетчик цикла
0007    E4 61                     IN       AL, 61H
0009    24 FE                     AND      AL, 0FEH
000B    E6 61                     OUT      61H, AL    ; Установка разряда 0 порта 61H в 0
                                                      ; для задания прямого управления динамиком
000D                     DIRECT:
000D    0C 02                     OR       AL, 2
000F    E6 61                     OUT      61H, AL    ; Включить динамик
0011    24 FD                     AND      AL, 0FDH
0013    E6 61                     OUT      61H, AL    ; Выключить динамик
0015    E2 F6                     LOOP     DIRECT
                         ;-----        Управление высотой звука динамика
0017    B0 B6                     MOV      AL, 10110110b
0019    E6 43                     OUT      43H, AL    ; Установка режима для 2-го канала
001B    B8 03E8                   MOV      AX, 1000   ; Выбор высоты
звука
001E    E6 42                     OUT      42H, AL
0020    8A C4                     MOV      AL, AH
0022    E6 42                     OUT      42H, AL     ; Занесение высоты звука в порт динамика
0024    E4 61                     IN       AL, 61H
0026    8A E0                     MOV      AH, AL
0028    0C 03                     OR       AL, 3
002A    E6 61                     OUT      61H, AL     ; Выбор режима управления динамикаом
002C    2B C9                     SUB      CX, CX
002E                     KILL_TIME:
002E    E2 FE                     LOOP     KILL_TIME   ; Цикл ожидания, во время которого
                                                       ; работает динамик
0030    8A C4                     MOV      AL, AH
0032    E6 61                     OUT      61H, AL     ; Выключение динамика
0034    CB                        RET
0035                     SPEAKER  ENDP

0035                     CODE     ENDS
                         END

                                  Фиг. 8.1 Управление динамиком

Другой порт ввода микросхемы 8255, порт 62H, обслуживает другие входы. Четыре его бита непосредственно соответствуют переключателям, показывающим объем памяти, подсоединенной к системному каналу ввода-вывода. Другие четыре бита имеют индивидуальное назначение. Два из них показывают тип системной ошибки. Программа обслуживания немаскируемого прерывания NMI использует эти биты для определения причины системной аварии. Бит 5 порта 62H используется для обратной связи с одним из каналов таймера-счетчика. Этот бит служит индикатором текущего выхода второго канала микросхемы 8253. Бит 4 порта 62H отражает текущее состояние ввода с кассетного магнитофона. Сзади у IBM PC, рядом с разъемом для подключения клавиатуры, имеется разъем для подключения кассетного магнитофона. При чтении данных с кассеты, этот бит используется для определения текущего значения, вводимого с кассеты.

Порт 61H - это порт вывода микросхемы 8255 в машине фирмы IBM. Всякий выходной порт захватывает (временно запоминает) данные, выводимые программой. Если бы аппаратура не запоминала данные, они бы пропали в течение микросекунды или около этого. Такое запоминание данных позволяет сохранять их значение в порте до тех пор, пока они снова не будут изменены программой. То есть, когда мы выводим значение, меняющее положение диффузора динамика, оно остается неизменными до тех пор, пока его не изменит программа.

На Фиг.8.2 показано значение битов порта 61H. Эти данные взяты из из технического описания.

При изучении управления динамиком имеют значение только биты 0 и 1. Из всех других - только бит 3 - управление двигателем кассетного магнитофона - и бит 7 - сброс ввода с клавиатуры - имеют какое-то значение для наших программ. Остальные биты предназначены только для инициализации и диагностики. Чтобы полностью разобраться в них, нужно детально изучить принципиальные схемы системы.

Возвращаясь к обсуждению управления динамиком, мы можем заметить, что биты 0 и 1 используются для непосредственного управления. Как показано на Фиг. 8.1, установка бита 0 в положение 0 включает прямое управление динамиком, блокируя механизм генерации звука микросхемой 8253. Этот метод используется во второй части програмы.

Бит Значение
0 Порт 2 таймера (упраление динамиком)
1 Прямое управление динамиком
2 Мультиплексный порт 62H
3 Управление мотором кассетного магнитофона
4 Включение контроля доступа на системной плате памяти
5 Включение контроля доступа в памяти каналов ввода-вывода
6 Временной контроль клавиатуры
7 Мультиплексный/сброса ввода с клавиатуры порт 60H

Фиг. 8.2 Значение битов порта 61H

Обратите внимание на то, как программа сбрасывает бит 0. Команда OUT включает все 8 бит порта 61H. Способа изменить только бит 0, оставив остальные биты нетронутыми, не существует. Если в программе нужно изменить только бит 0, она должна считать из порта текущее значение других разрядов. К счастью, микросхема 8255 допускает прямое программное чтение выводных портов. Последовательность команд


IN     AL , 61H
AND    AL , 0FFH
OUT    61H, AL

читает текущий код из выводного порта, затем команда AND сбрасывает младший бит, а команда OUT посылает результат в выводной порт. Если бы программа вывела в порт просто число 0, динамик работал бы верно, но клавиатура была бы выключена. Работая с любым портом вывода побитовой настройки, стройте программу так, чтобы она не влияла ни на один из других бит, если только вы не собираететсь изменять и их. Оставшаяся часть первой программы на Фиг.8.1 изменяет значение бита 1 выходного порта. Исходное значение порта 61H находится уже в регистре AL, так что программе не нужно читать его при каждом выполнении цикла. Регистр CX используется таким образом, чтобы выполнить цикл 64K раз. При выполнении программы вам, возможно, не удастся услышать звук, генерируемый программой. В этом случае попытайтесь вставить несколько добавочных команд NOP в цикл DIRECT. Это снизит частоту тона.

Вторая часть программы на Фиг. 8.1 для генерации тональности использует таймер-счетчик 8253. Прежде чем двигаться дальше, обсудим функционирование микросхемы 8253, чтобы понять, как она используется в системе. Микросхема 8253 фирмы Intel содержит три 16-битовых счетчика, которые могут быть использованы в системе для счета или задания временных интервалов. В один из счетчиков программа загружает 16-битовое значение. Содержимое счетчика уменьшается на единицу по каждому импульсу от таймера; частота импульсов, подводимых с таймера ко всем трем каналам, равна 1.19 МГц. Это означает, что содержимое счетчика уменьшается на единицу каждые 840 наносекунд. Каждый из трех каналов имеет выход. Строка контроля выхода изменяется всякий раз, когда содержимое счетчика достигает нуля. Командами управления определяют способ, которым микросхема 8253 ведет счет.

Выходы этих трех каналов счетчика-таймера подключаются к различным узлам системной платы. Канал 0 подключается к контроллеру прерываний 8259. Система использует этот канал для порождения прерывания времени суток. Канал 1 соединен с контроллером прямого доступа к памяти (ПДП или DMA) 8237, и использовать этот канал схемы 8253 нельзя, так как смена кода в этом счетчике с большой вероятностью уничтожит вашу программу и все другие данные в памяти системы. Канал 2 подключен к динамику для генерации звука.

Позже мы вернемся к каналу 0 микросхемы 8253. Канал 2 Дает выход на динамик. Для установки канала таймера программа посылает код 0B6H в порт 43H, управляющий порт микросхемы 8253. Тем самым канал 2 таймера-счетчика настраивается на работу в качестве делителя частоты. Таймер делит исходную частоту - в данном случае 1.19 МГц - на 16-битовое число, которое программа загружает в регистр канала 2. Регистр канала 2 расположен по адресу порта 42H (канал 0 - это порт 40H и, поскольку вы никогда не должны изменять содержимое канала 1, задачу определения адреса его порта мы оставляем вам). Программа в примере загружает в регистр канала число 1000. Это означает, что на выходе вы услышите частоту 1190 Гц. На самом деле, вы услышите основную частоту 1190 Гц плюс обертоны, вызванные прямоугольной формой сигнала таймера.

Заметим, что число 1000 - 16-битовое, в то время как порт 42H - 8-битовый. Команда установки режима работы, которую мы послали в порт 43H, сообщила микросхеме 8253, что в нее будет выводиться 16-битовое число в виде двух 8-битовых. Сначала посылается младший значащий байт, а за ним следует старший. Такая двухшаговая процедура загружает в канальный регистр требуемое значение.

Далее программа должна дать управляющему порту 61H такую установку, чтобы он пропускал сигнал на динамик. Для этого программа устанавливает равными 1 биты 0 и 1 управляющего порта. Заметим, что программа в начале сохраняет первоначальное значение кода из управляющего порта и восстанавливает его в конце. Это отключает динамик по окончании звука. Если этот способ недостаточен, - например, если программа генерирует звук тогда, когда не совсем ясно, был ли выключен динамик - можно выключить его, сбросив в нуль бит 1 порта 61H.

Эти два метода управления динамиком наиболее прямолинейны. Эти методы можно пытаться комбинировать в поисках интересных эффектов. После установки на вывод звука при помощи микросхемы 8253 можно модулировать выходной сигнал посредством битов 1, 0 или обоих, порта 61H, а также менять число в канальном счетчике при включенном динамике. Программу на Фиг. 8.1 можно изменить так, чтобы она выводила значение регистра CX при каждой итерации цикла. Это приведет к тому, что частота сигнала из динамика будет расти от очень низкого к очень высокому тону. Работая с этими тремя управляющими значениями, вы сможете создать множество интересных эффектов.