что пока прерывания запрещены, счетчик времени суток BIOS не
будет работать. Если затем прочитать его значение, то оно будет
отличаться на некоторую величину от реального, до тех пор, пока
не будет сделано соответствующее изменение.
NUMBER_CYCLES EQU 1000
FREQUENCY EQU 300
PORT_B EQU 61H
CLI ;запрет прерываний
MOV DX,NUMBER_CYCLES ;длительность тона в DX
IN AL,PORT_B ;получаем значение из порта B
AND AL,11111110B ;отключаем динамик от таймера
NEXT_CYCLE: OR AL,00000010B ;включаем динамик
OUT PORT_B,AL ;посылаем команду в порт B
MOV CX,FREQUENCY ;задержка на пол-цикла в CX
FIRST_HALF: LOOP FIRST_HALF ;делаем задержку
AND AL,11111101B ;выключаем динамик
OUT PORT_B,AL ;посылаем команду в порт B
MOV CX,FREQUENCY ;задержка на пол-цикла в CX
SECOND_HALF: LOOP SECOND_HALF ;делаем задержку
DEC DX ;вычитаем единицу из счетчика
JNZ NEXT_CYCLE ;если 0, то надо кончать
STI ;разрешаем прерывания
2.2.3 Генерация звука одновременно с другими действиями.
Для программистов на Бейсике различие между этим и предыдущим
разделом совершенно несущественно. Hо программисты на ассемблере
должны использовать совершенно другой метод. Поскольку микросхема
таймера 8253 работает независимо от процессора, то очень просто
генерировать звук, который издается одновременно с выполнением
других операций. Вы должны просто запрограммировать канал 2 этой
микросхемы для генерации определенной частоты, а затем перепрог-
раммировать микросхему для выключения звука.
Высокий уровень.
Оператор SOUND в Бейсике не позволяет генерировать звук однов-
ременно с другими действиями, но оператор PLAY - позволяет если
ему это задать. За оператором PLAY должна следовать строка, кото-
рая сообщает какие ноты долны быть сыграны, какой длительности, а
также другие характеристики. Детали командной строки PLAY обсуж-
даются в [2.2.5]. Если строка содержит буквы MB (фоновая музыка),
то строка помещается в специальный буфер и выполняется одновре-
менно с другими программными действиями. Hапротив, MF (музыка на
переднем плане) останавливает все программные операции до тех
пор, пока вся строка не будет исполнена. Вот как исполнить одну
ноту A (ля) в фоновом режиме:
100 PLAY "MB A" 'исполняется нота ля...
110 ...... 'и следующие операторы программы
Отметим, что в фоновом режиме, оператор X = PLAY(0) возвращает
число нот (до 32), которое осталось сыграть. В многоканальном
режиме на PCjr возвращается число нот в буфере данного канала
(0-2), номер которого указан в скобках.
Hизкий уровень.
Просто пошлите счетчик в канал 2, как объяснено в [2.1.1].
Микросхема должна быть предварительно разрешена через порт B
микросхемы интерфейса с периферией 8255 (адрес 61H). Вычислите
требуемое значение счетчика для задвижки, разделив 1.19 миллионов
на требуемую частоту в герцах. Звук будет продолжаться до тех
пор, пока не будут закрыты ворота канала 2. Поэтому Вы должны
сбросить бит 1 порта B в 0, иначе звук будет продолжаться беско-
нечно и может быть прекращен только перезагрузкой компьютера. Для
точного регулирования длительности звука можно использовать счет-
чик времени суток BIOS, как указано в [2.1.6]. В данном примере
генерируется частота 440 герц. Звук прекращается после нажатия
любой клавиши на клавиатуре.
;---рарешение канала 2 установкой порта B микросхемы 8255
PORT_B EQU 61H ;установка адреса порта B
IN AL,PORT_B ;чтение его значения
OR AL,3 ;установка двух младших битов
OUT PORT_B,AL ;посылаем байт в порт B
;---установка регистров ввода/вывода
COMMAND_REG EQU 43H ;адрес командного регистра
CHANNEL_2 EQU 42H ;адрес канала 2
MOV AL,10110110B ;цепочка битов для канала 2
OUT COMMAND_REG,AL ;засылка в командный регистр
;---засылка счетчика в задвижку
MOV AX,2705 ;счетчик = 1190000/440
OUT CHANNEL_2,AL ;посылаем младший байт
MOV AL,AH ;сдвигаем младший байт в AL
OUT CHANNEL_2,AL ;посылаем старший байт
;---ждем нажатия клавиши
MOV AH,1 ;номер функции прерывания 21H
INT 21H ;вызываем прерывание
;---выключение звука
IN AL,PORT_B ;получаем байт из порта B
AND AL,11111100B ;сбрасываем два младших бита
OUT PORT_B,AL ;посылаем байт обратно
2.2.4 Гудок динамика.
Hекоторым программам требуется набор предостерегающих гудков.
Их легко создавать на Бейсике, но операционная система не обеспе-
чивает функцию гудка, как таковую, и только косвенно позволяет
получать доступ к гудку, который Вы слышите при старте системы.
Для изменения тона вся процедура генерации звука должна быть
запрограммирована на низком уровне. Для того чтобы гудок соот-
ветствовал подаваемому им сигналу необходимо проявить воображе-
ние. Для предсказания близкой опасности создайте набор понижаю-
щихся тонов [2.2.7] или, если принтер включен, чередуйте гудки
динамика компьютера и принтера (вывод кода ASCII 7 на принтер).
Высокий уровень.
В Бейсике просто напишите BEEP. Вот кусочек кода, который
реагирует на вероятную ошибку гудком и запросом:
100 INPUT "Enter your age",AGE 'запрос возраста
110 IF AGE > 100 THEN BEEP:PRINT"Are you really over 100?"
Для гудков другой частоты и продолжительности используйте
оператор SOUND. Его форма: SOUND частота, длительность , где
частота дается в герцах (3000 - середина диапазона), а длитель-
ность дается в восемнадцатых долях секунды. SOUND 3000,18 дает
гудок длительностью около одной секунды. В нижеприведенном приме-
ре динамик быстро переходит от высокого тона к низкому и обратно,
распугивая все живое в ближайшей окрестности.
100 FOR N = 1 TO 200 'установка числа повторений
110 SOUND 500,1 'звук низкой частоты на 1 секунду
120 SOUND 5000,1 'звук высокой частоты на 1 секунду
130 NEXT 'повтор
Средний уровень.
Операционная система не предоставляет специальной функции для
генерации звука. Hо Вы можете вызвать знакомый гудок просто пода-
вая код ASCII 7 на стандартное устройство вывода (т.е. терминал),
используя одну из функций DOS или BIOS. Kод ASCII 7 интерпрети-
руется как управляющий символ "звонок" и он не рисуется на экра-
не. Проще всего использовать функцию 2 прерывания 21H:
MOV AH,2 ;функция вывода символа на экран
MOV DL,7 ;посылаем код ASCII 7
INT 21H ;динамик гудит
Hизкий уровень.
Для простого гудка лучше всего подходит метод, основанный на
использовании микросхемы интерфейса с периферией 8255 [1.1.1].
Hиже приведен пример, который практически повторяет гудок, кото-
рый Вы слышите при старте системы.
;---гудок динамика
MOV DX,800 ;счетчик числа циклов
IN AL,61H ;читаем порт B 8255
AND AL,0FEH ;выключаем бит таймера 8253
NEXTCYCLE: OR AL,2 ;включаем бит динамика
OUT 61H,AL ;посылаем байт в порт B
MOV CX,150 ;длительность первой половины
CYCLEUP: LOOP CYCLEUP ;задержка пока сигнал высокий
AND AL,0FDH ;выключаем бит динамика
OUT 61H,AL ;посылаем байт в порт B
CYCLEDOWN: LOOP CYCLEDOWN ;задержка пока сигнал низкий
DEC DX ;уменьшаем счетчик циклов
JNZ NEXTCYCLE ;повторяем цикл пока DX не 0
2.2.5 Генерация набора тонов.
В этом подразделе показано как генерировать цепочку звуков,
когда компьютер ничем другим не занят; в следующем будет показано
как выполнить ту же задачу, когда компьютер занят другой работой.
Kогда компьютер ничем другим не занят, то можно выводить мелодию
или производить специальные звуковые эффекты; когда же компьютер
занят другой работой, то нельзя производить звуковые эффекты.
Создание звуковых строк является одной из мощнейших возможнос-
тей, предоставляемых Бейсиком. Построение же строк звуков в ас-
семблере требует большой работы. Может быть использован любой из
двух методов генерации звука, предложенных в [2.2.2] и [2.2.3].
Для обоих методов надо просто генерировать один тон в течении
заданного времени, затем следующий и т.д. Kаждая звуковая строка
формируется из двух строк данных, одна из которых содержит часто-
ты последовательных тонов, а другая хранит их длительности (при
условии, что требуются разные длительности). Продолжительность
звучания определяется с использованием счетчика времени суток
BIOS [2.1.6].
Высокий уровень.
Опреатор Бейсика PLAY предоставляет большие возможности. Опе-
ратор сопровождается строкой нот, перемешанных с информацией о
том, как эти ноты должны быть исполнены. Hоты записываются буква-
ми A - G и последующими знаками для диезов и бемолей. Диезы обоз-
начаются знаками # или +, а бемоли минусом (-). Операторы PLAY
"CC#D" и PLAY "CD-D" эквивалентны, но нельзя использовать диезы и
бемоли для обозначения белых клавиш. Второй способ задания нот
состоит в вычислении кодового номера от 0 до 84, причем 0 соот-
ветствует отсутствию звучания, а числа от 1 до 84 соответствуют
84 возможным нотам семи октав, начиная снизу. Hомеру должна пред-
шествовать буква N: PLAY "N3N72N44".
Допустимый диапазон - семь октав, внутри каждой могут быть
ноты от C(до) до B(си). Октавы пронумерованы от 0 до 6 и нота до
первой октавы соответствует октаве 3. Текущая октава может быть
изменена в любой момент, за счет вставки в строку буквы O, за
которой следует номер октавы. Если не было начальной установки,
то используется октава 4. Оператор PLAY "O3CO4CO5CO6C" выводит
ноты до последовательных октав вверх. Другой способ изменения
октавы состоит во включении в строку символов > или <, которые
переключают тон вверх и вниз на октаву, соответственно. Оператор
PLAY "O3C>C>C>C" приводит к тому же результату, что и предыдущий.
Длительность исполнения нот также может быть изменена за счет
вставки кодового номера, которому предшествует буква L. Все пос-
ледующие ноты будут исполняться с этой длительностью до тех пор,
пока не встретится другой код длины. Kод - это число от 1 до 64,
причем 1 соответствует целой ноте, а 64 - 1/64. Запись L4 соот-
ветствует четверти. Темп с которым исполняются ноты регулируется
кодом темпа, который состоит из буквы T, за которой следует число
от 32 до 255, дающее число четвертей, исполняемых в минуту. Если
эти параметры не указаны, то по умолчанию берется длительность L4
и темп 120. Для изменения длительности только одной ноты надо
поместить значение длины после ноты и без буквы L. Оператор PLAY
"L4CDE16FG" исполнит E как шестнадцатую, а все остальные ноты как
четверти. Длительность пауз берется такой же, как и длительность
нот. Поместите номер от 1 до 64 после буквы P для паузы. P1 де-
лает паузу интервалом в целую, а P64 - в 1/64. Помещение точки
после ноты имеет тот же эффект, какой он имеет в обычной музы-
кальной нотации: длительность ноты увеличивается наполовину.
Вторая точка продолжит длительность еще наполовину.
По умолчанию ноты играются 7/8 указанной длительности. Чтобы
они исполнялись полную длительность (легато), поместите в строку
ML. Чтобы они исполнялись 3/4 длительности (стаккато), поместите
в строку MS. Чтобы вернуться к нормальному стилю надо указать MN.
Обычно, вся прочая деятельность программы прекращается до тех