ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 04.07.2020
Просмотров: 3161
Скачиваний: 1
порта B, который связан с динамиком (бит 1). Порт B имеет адрес
61H (хотя AT не имеет микросхемы интерфейса с периферией 8255 как
таковой, он использует для этой цели тот же адрес порта и тот же
бит). Если программа переключает значение бита с максимально
возможной частотой, то частота слишком высокая, чтобы быть полез-
ной. Поэтому между двумя переключениями надо вставлять пустой
цикл. Помните, что бит 0 порта B управляет воротами канала 2
микросхемы таймера, который в свою очередь связан с динамиком.
Поэтому этот бит должен быть сброшен, отсоединяясь от канала
таймера. На рис. 2-4 показано как этот метод устанавливает часто-
ту звука.
В следующем примере введены две переменные. Одна, обозначенная
"FREQUENCY", используется в качестве счетчика в пустом цикле
между действиями включения и выключения. Чем меньше ее значение,
тем быстрее происходит изменение бита и тем больше частота. Пере-
менная же "NUMBER_CYCLES" устанавливает продолжительность тона.
Она говорит сколько раз должен быть повторен процесс включения и
выключения. Чем больше это число, тем дольше звучит данный звук.
Отметим, что для этой процедуры аппаратные прерывания должны
быть запрещены. Причина этого в том, что прерывание таймера
происходит с такой частотой и регулярностью (18.2 раза в секун-
ду), что оно будет существенно влиять на частоту. Имейте ввиду,
что пока прерывания запрещены, счетчик времени суток 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 Генерация звука одновременно с другими действиями.
Для программистов на Бейсике различие между этим и предыдущим
разделом совершенно несущественно. Но программисты на ассемблере
должны использовать совершенно другой метод. Поскольку микросхема
таймера 8253 работает независимо от процессора, то очень просто
генерировать звук, который издается одновременно с выполнением
других операций. Вы должны просто запрограммировать канал 2 этой
микросхемы для генерации определенной частоты, а затем перепрог-
раммировать микросхему для выключения звука.
Высокий уровень.
Оператор SOUND в Бейсике не позволяет генерировать звук однов-
ременно с другими действиями, но оператор PLAY - позволяет если
ему это задать. За оператором PLAY должна следовать строка, кото-
рая сообщает какие ноты долны быть сыграны, какой длительности, а
также другие характеристики. Детали командной строки PLAY обсуж-
даются в [2.2.5]. Если строка содержит буквы MB (фоновая музыка),
то строка помещается в специальный буфер и выполняется одновре-
менно с другими программными действиями. Напротив, MF (музыка на
переднем плане) останавливает все программные операции до тех
пор, пока вся строка не будет исполнена. Вот как исполнить одну
ноту A (ля) в фоновом режиме:
100 PLAY "MB A" 'исполняется нота ля...
110 ...... 'и следующие операторы программы
Отметим, что в фоновом режиме, оператор X = PLAY(0) возвращает
число нот (до 32), которое осталось сыграть. В многоканальном
режиме на PCjr возвращается число нот в буфере данного канала
(0-2), номер которого указан в скобках.
Низкий уровень.
Просто пошлите счетчик в канал 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 Гудок динамика.
Некоторым программам требуется набор предостерегающих гудков.
Их легко создавать на Бейсике, но операционная система не обеспе-
чивает функцию гудка, как таковую, и только косвенно позволяет
получать доступ к гудку, который Вы слышите при старте системы.
Для изменения тона вся процедура генерации звука должна быть
запрограммирована на низком уровне. Для того чтобы гудок соот-
ветствовал подаваемому им сигналу необходимо проявить воображе-
ние. Для предсказания близкой опасности создайте набор понижаю-
щихся тонов [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 'повтор
Средний уровень.
Операционная система не предоставляет специальной функции для
генерации звука. Но Вы можете вызвать знакомый гудок просто пода-
вая код ASCII 7 на стандартное устройство вывода (т.е. терминал),
используя одну из функций DOS или BIOS. Код ASCII 7 интерпрети-
руется как управляющий символ "звонок" и он не рисуется на экра-
не. Проще всего использовать функцию 2 прерывания 21H:
MOV AH,2 ;функция вывода символа на экран
MOV DL,7 ;посылаем код ASCII 7
INT 21H ;динамик гудит
Низкий уровень.
Для простого гудка лучше всего подходит метод, основанный на
использовании микросхемы интерфейса с периферией 8255 [1.1.1].
Ниже приведен пример, который практически повторяет гудок, кото-
рый Вы слышите при старте системы.
;---гудок динамика
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 Генерация набора тонов.
В этом подразделе показано как генерировать цепочку звуков,
когда компьютер ничем другим не занят; в следующем будет показано
как выполнить ту же задачу, когда компьютер занят другой работой.
Когда компьютер ничем другим не занят, то можно выводить мелодию
или производить специальные звуковые эффекты; когда же компьютер
занят другой работой, то нельзя производить звуковые эффекты.
Создание звуковых строк является одной из мощнейших возможнос-
тей, предоставляемых Бейсиком. Построение же строк звуков в ас-
семблере требует большой работы. Может быть использован любой из
двух методов генерации звука, предложенных в [2.2.2] и [2.2.3].
Для обоих методов надо просто генерировать один тон в течении
заданного времени, затем следующий и т.д. Каждая звуковая строка
формируется из двух строк данных, одна из которых содержит часто-
ты последовательных тонов, а другая хранит их длительности (при
условии, что требуются разные длительности). Продолжительность
звучания определяется с использованием счетчика времени суток
BIOS [2.1.6].
Высокий уровень.
Опреатор Бейсика PLAY предоставляет большие возможности. Опе-
ратор сопровождается строкой нот, перемешанных с информацией о
том, как эти ноты должны быть исполнены. Ноты записываются буква-
ми A - G и последующими знаками для диезов и бемолей. Диезы обоз-
начаются знаками # или +, а бемоли минусом (-). Операторы PLAY
"CC#D" и PLAY "CD-D" эквивалентны, но нельзя использовать диезы и
бемоли для обозначения белых клавиш. Второй способ задания нот
состоит в вычислении кодового номера от 0 до 84, причем 0 соот-
ветствует отсутствию звучания, а числа от 1 до 84 соответствуют
84 возможным нотам семи октав, начиная снизу. Номеру должна пред-
шествовать буква N: PLAY "N3N72N44".
Допустимый диапазон - семь октав, внутри каждой могут быть
ноты от C(до) до B(си). Октавы пронумерованы от 0 до 6 и нота до
первой октавы соответствует октаве 3. Текущая октава может быть
изменена в любой момент, за счет вставки в строку буквы O, за
которой следует номер октавы. Если не было начальной установки,
то используется октава 4. Оператор PLAY "O3CO4CO5CO6C" выводит
ноты до последовательных октав вверх. Другой способ изменения
октавы состоит во включении в строку символов > или <, которые
переключают тон вверх и вниз на октаву, соответственно. Оператор
PLAY "O3C>C>C>C" приводит к тому же результату, что и предыдущий.
Длительность исполнения нот также может быть изменена за счет
вставки кодового номера, которому предшествует буква L. Все пос-
ледующие ноты будут исполняться с этой длительностью до тех пор,
пока не встретится другой код длины. Код - это число от 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.
Обычно, вся прочая деятельность программы прекращается до тех
пор, пока не будет сыграна строка. Для того чтобы выполнялись
операторы, следующие за оператором PLAY, а строка исполнялась в
фоновом режиме, поместите в строку MB. Для восстановления нор-
мальной ситуации напишите MF.
Наконец, оператор PLAY позволяет исполнять подстроки внутри
длинной строки. Имеется в виду, что часть исполняемой строки
может быть введена как обычная строковая переменная, а затем эта
переменная может быть вызвана из строки сформированной в операто-
ре PLAY. Например, если S$ = "EEEEE", то в операторе PLAY
"CDXS$;FG" нота E будет повторена 5 раз. Отметим, что имени пере-
менной должна предшествовать буква X, а за именем следовать точка
с запятой (;). (Для компилируемых программ применяется другой
метод, использующий переменную VARPTR$ - детали см. в руководстве
по Бейсику).
В приведенном примере исполняется знакомый бой дедушкиных
часов. В строке сначала устанавливается стиль исполнения легато,
затем темп и начальная октава, и, наконец, четыре ноты, пауза, и
те же самые четыре ноты, но в обратном порядке. Пробелы в строке
включены исключительно для удобства программиста - Бейсик игнори-
рует их.
100 PLAY "ML T40 O3 ECD<G P32 G>DEC"
Благодаря наличию генератора звука PCjr добавляет к оператору
PLAY две возможности. Во-первых, допускается параметр V, устанав-
ливающий громкость. Выражение V5 устанавливает (или изменяет)
громкость на уровень 5. Допустимый диапазон от 0 до 15, причем по
умолчанию берется 8. 0 полностью подавляет звук. Во-вторых, с
помощью оператора PLAY можно одновременно исполнять три звуковых
строки. Поместите все три строки в одну программную строку, раз-
деляя их запятыми. Для того чтобы иметь возможность использовать
эти специальные свойства, Вы должны предварительно разрешить
внешний динамик с помощью оператора SOUND ON.
100 SOUND ON
110 PLAY "...........","..........","............"
Низкий уровень.
В примере для генерации звука используется микросхема таймера
8253. Здесь просто исполняются 8 нот, но небольшая модификация
может сильно расширить возможности этой процедуры. Имеется три
строки данных. Первая устанавливает длительность каждой ноты, как