Файл: jourdain_spravochnik_programmista.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.07.2020

Просмотров: 3104

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

импульсов счетчика времени суток. Для периода в пределах одного

часа достаточно 16 бит - более длинные периоды требуют более

сложных 32-битовых операций. Это число импульсов добавляется к

младшему слову текущего значения счетчика времени суток и запоми-

нается в ALARMCOUNT.

Затем вектор прерывания 1CH изменяется таким образом, чтобы он

указывал на процедуру ALARM. Помните, что как только вектор будет

изменен, ALARM будет автоматически вызываться 18.2 раза в секун-

ду. При вызове эта процедура читает текущее значение счетчика

времени суток через прерывание 1AH и сравнивает с ALARMCOUNT. При

совпадении этих величин вызывается процедура BEEP (также не пока-

занная здесь - см. [2.2.4]), которая выдает звуковой сигнал. В

противном случае происходит возврат. Обычный код возврата из

аппаратных прерываний (MOV AH,20H / OUT 20H,AL) включать в проце-

дуру не нужно, так как он будет в прерывании таймера. Будьте

внимательны и не забудьте сохранить изменяемые регистры.


;---в сегменте данных

MINUTES DW 0 ;хранит число минут до звонка

ALARMCOUNT DW 0 ;хранит счетчик времени для звонка


;---установка ожидаемого значения счетчика времени суток

CALL REQUEST_MINUTES ;запрос числа минут до звонка

MOV AX,MINUTES ;пересылка в AX

MOV BX,1092 ;число импульсов счетчика в минуте

MUL BX ;умножаем - результат в AX

;получаем текущее значение счетчика

MOV AH,0 ;номер функции чтения счетчика

INT 1AH ;читаем значение, младший байт в DX

;складываем оба значения

ADD AX,DX ;

MOV ALARMCOUNT,AX ;получаем нужное значение счетчика



;---заменяем вектор пустого прерывания

PUSH DS ;сохраняем сегмент данных

MOV AX,SEG ALARM ;берем сегмент процедуры ALARM

MOV DS,AX ;помещаем его в DS

MOV DX,OFFSET ALARM ;берем смещение процедуры

MOV AL,1CH ;номер изменяемого вектора

MOV AH,25H ;функция изменения вектора

INT 21H ;меняем вектор

POP DS ;восстанавливаем сегмент данных

;

;---дальше продолжается программа

;

;---в конце программы возвращаем вектор прерывания

MOV DX,0FF53H ;оригинальные значения для

MOV AX,0F000H ;прерывания 1CH

MOV DS,AX ;помещаем сегмент в DS

MOV AL,1CH ;номер изменяемого вектора

MOV AH,25H ;номер функции

INT 21H ;восстанавливаем вектор


;---процедура выдачи звукового сигнала

ALARM PROC FAR ;создаем длинную процедуру

PUSH AX ;сохраняем изменяемые регистры

PUSH CX ;

PUSH DX ;

;---читаем счетчик времени суток

MOV AH,0 ;номер функции чтения счетчика

INT 1AH ;читаем значение счетчика

;---сравниваем с требуемым значением

MOV CX,ALARMCOUNT ;берем требуемое значение

CMP DX,CX ;сравниваем с текущим

JNE NOT_YET ;если неравны, то на выход

;---выдаем звуковой сигнал, если значения совпали

CALL BEEP ;эта процедура не показана

;---иначе возвращаемся из прерывания

NOT_YET: POP DX ;восстанавливаем регистры

POP CX ;


POP AX ;

IRET ;возврат из прерывания

ALARM ENDP ;конец процедуры




2.1.8 Генерация случайных чисел с помощью микросхемы таймера.




Для генерации последовательности случайных чисел требуются

сложные математические манипуляции. Но иногда программе в опреде-

ленный момент требуется только одно случайное число. В этом слу-

чае случайное число может быть получено просто чтением из канала

микросхемы таймера. Бейсик использует это число в качестве ядра,

по которому генерируется случайная последовательность. Конечно,

Вы не можете использовать ряд последовательно считанных значений

в качестве случайной последовательности, так как сами по себе

интервалы времени между считываниями будут неслучайными.


100 RANDOMIZE TIMER 'сброс генератора случайных чисел

110 PRINT RND,RND,RND 'печать трех случайных чисел


в результате получаем: .7122483 .4695052 .9132487


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


Поскольку регистр счетчика канала таймера перезагружается

снова и снова данным числом (а в промежутках идет счет вниз до

0), выберите в качестве загружаемого в счетчик значения число,

равное требуемому диапазону случайных чисел. Например, для полу-

чения случайного значения часа дня загружайте в счетчик 23.

Лучше всего использовать режим 3 канала 2 (порт 42H) микросхе-

мы таймера [2.1.1]. Сначала установите для счетчика желаемый

диапазон случайных чисел (в примере используется 10000, что при-

водит к выдаче случайного числа в диапазоне от 0 до 9999). Затем,

чтобы получить из канала случайное число, надо подать команду

командному регистру микросхемы таймера через порт 43H перенести

текущее значение счетчика в регистр "задвижки", для чего надо

сбросить биты 4 и 5. Этот перенос в регистр задвижки не мешает

продолжающемуся счету. Затем установите оба бита 4 и 5 командного

регистра, чтобы процессор мог читать из регистра задвижки. После

этого две инструкции IN дадут сначала младший, а затем старший

байт в регистре AL. Наконец, восстановите первоначальное значение

регистра задвижки, чтобы счет продолжался в пределах указанного

диапазона времени.


;---установка адресов портов

COMMAND_REG EQU 43H ;адрес командного регистра

CHANNEL_2 EQU 42H ;адрес канала 2

CALL SET_COUNT ;установка диапазона

.

;---здесь программа работает, а затем требует случайное число

.

CALL GET_NUMBER ;получение случайного числа

.

.



;---начинаем отсчет канала 2

SET_COUNT PROC

MOV AL,10110110B ;канал 2, режим 2, оба байта

OUT COMMAND_REG,AL ;посылаем в командный регистр

MOV AX,10000 ;значение счетчика

OUT CHANNEL_2,AL ;посылаем младший байт

MOV AL,AH ;передвигаем старший байт в AL

OUT CHANNEL_2,AL ;посылаем старший байт

RET

SET_COUNT ENDP

;---получение случайного числа

READ_NUMBER PROC

;---пересылаем значение счетчика в регистр задвижки

MOV AL,10000110B ;требуемая команда


OUT COMMAND_REG,AL ;посылаем в командный регистр

;---читаем значение счетчика

MOV AL,10110110B ;запрос на чтение/запись

OUT COMMAND_REG,AL ;посылаем запрос

IN AL,CHANNEL_2 ;получаем младший байт

MOV AH,AL ;временно храним его в AH

IN AL,CHANNEL_2 ;получаем старший байт

CALL SET_COUNT ;восстанавливаем задвижку

SWAP AH,AL ;ставим байты на место

RET ;теперь случайное число в AX

READ_NUMBER ENDP



Раздел 2. Создание звука.




Бейсик оснащен достаточно изощренными средствами для генерации

звука, однако операционная система позволяет только просто подать

звуковой сигнал. Если Вы хотите получить какие-либо сложные зву-

ки, то Вы должны прямо программировать микросхему таймера 8253.

Канал 2 этой микросхемы прямо связан с динамиком компьютера.

Когда этот канал программируется в режиме 3, то он посылает пря-

моугольные волны данной частоты. Из-за простоты динамика он сгла-

живает края прямоугольной волны, получая более приятную для слуха

синусоидальную волну. К сожалению, микросхема 8253 не может ме-

нять амплитуду волны, поэтому мы не можем менять громкость звука,

издаваемого динамиком.

Динамик имеет не один, а два входа для генерации звука. На

рис. 2-2 в [2.1.1] показано, что кроме микросхемы таймера, сигнал

посылает также микросхема интерфейса с периферией 8255 [1.1.1].

Частота импульсов каждой микросхемы может быть изменена, поэтому

комбинируя воздействия этих двух источников мы можем получать

специальные звуковые эффекты.

Только PCjr имеет специальную микросхему, управляющую генера-

тором звука. Он может одновременно выдавать три разных тона, плюс

шум для звуковых эффектов. Громкость каждого из трех каналов

может устанавливаться независимо. Другой уникальной возможностью

PCjr является то, что он может управлять внешним источником зву-

ка, таким как кассетный магнитофон.




2.2.1 Программирование генератора звука 76496 (только PCjr).




PCjr снабжен 4-канальным генератором звука, в котором три

канала генерируют тона, а четвертый служит для генерации шума для

звуковых эффектов. Все четыре канала программируются независимо,

причем каждый из них имеет свой регулятор громкости, а затем

выход со всех них объединяется в единый звуковой сигнал. Исполь-

зуется микросхема комплексного генератора звука TI SN76496N. Она

имеет 8 регистров - 2 для каждого канала - и все они адресуются

через один порт с адресом 0C0H. Этот порт служит только для запи-

си; если подать инструкцию IN, то вся система будет заморожена.

PCjr имеет также разъем для внешнего источника звука. При

старте системы звуковой канал получает выходной сигнал от микрос-

хемы таймера 8253. Но этот канал может быть переключен на микрос-

хему генератора звука или любой из двух внешних звуковых входов.

Это достигается изменением битов 5 и 6 порта B микросхемы интер-


фейса с периферией 8255 (адрес порта 61H - см. [1.1.1]). Значение

битов следующее:


Биты 6 и 5 Выбранная функция


00 микросхема таймера 8253

01 вход с кассетного магнитофона

10 вход канала ввода/вывода

11 генератор звука 76496


Для выбора источника звука в BIOS PCjr добавлена функция 80H

прерывания 1AH. Поместите в AL номер кода от 0 до 3, в соответст-

вии с вышеприведенной таблицей, и вызовите функцию. Возвращаемых

регистров нет. Генератор звука 76496 должен использовать этот

звуковой канал, поскольку он не может управлять внутренним дина-

миком PCjr.

В общем случае, когда байт данных посылается генератору звука,

то биты 4-6 содержат код идентификации, сообщающий какому из

восьми регистров предназначены данные. Эти коды такие:


Биты 6-4 Адресуемый регистр


000 Частота первого тона

001 Громкость первого тона

010 Частота второго тона

011 Громкость второго тона

100 Частота третьего тона

101 Громкость третьего тона

110 Частота четвертого тона

111 Громкость четвертого тона


В случае регистров частоты тонов требуются два байта. Значение

битов при этом следующее:


байт 1: биты 0-3 младшие 4 бита частоты

4-6 код идентификации регистра

7 всегда равен 1

байт 2: биты 0-5 старшие 6 битов частоты

6 не используется

7 всегда равен 0



Для установки частоты тона в регистр посылается 10-битное значе-

ние, которое после деления на 111 843 дает желаемую частоту в

герцах. Таким образом, доступны частоты, начиная с 110 герц вверх

(111 843/2^10). Как только регистр инициализирован (и соответст-

венно установлен порт B микросхемы 8255), немедленно начинается

звуковой сигнал и продолжается до тех пор, пока он не будет прек-

ращен. Не обязательно для изменения частоты посылать новые два

байта. Если послан только второй байт (старшие 6 битов частоты),

то он автоматически заменяет соответствующие данные в канале, к

которому была последняя адресация. Эта возможность позволяет

плавно варьировать частоту.

Генератору шума для программирования нужен только один байт.

Значение битов для него следующее:


биты 0-1 плотность шума

2 качество шума

3 не используется

4-6 код идентификации регистра

7 всегда установлен в 1


Качество шума устанавливается на белый шум (постоянное шипение),

когда бит 2 равен 1 и на периодический шум (волны звука), когда

бит 2 равен 0. Плотность звука увеличивается при увеличении битов

0-1 от 00B до 10B; когда они установлены в 11B, то звук меняется

в зависимости от выходного тона канала 3.

Громкость каждого из четырех каналов изменяется ослаблением

основного сигнала. Для этой установки требуется только один байт.

Значение его битов следующее:


биты 0-3 ослабление сигнала


4-6 код идентификации регистра

7 всегда установлен в 1


Когда все 4 бита данных равны 0, то громкость максимальна. Когда

все они равны 1, то звук полностью подавляется. Для получения

звука промежуточной громкости может быть использована любая ком-

бинация битов. Бит 0 ослабляет звук на 2 Дб (децибелла), бит 1 -

на 4 Дб, бит 2 - на 8 Дб и бит 3 - на 16 Дб. Максимальное ослаб-

ление равно 28 Дб.




2.2.2 Генерация тона.




Этот подраздел объясняет как производить звук, когда компьютер

не занят ничем другим; в [2.2.3] показано как это сделать, когда

производятся другие действия. Забавно, но для программистов на

ассемблере последнее проще. Для этого достаточно запрограммиро-

вать микросхему таймера 8253, которая работает независимо от

процессора. В приведенном здесь методе процессор непосредственно

управляет динамиком, поэтому программе приходится выполнять рабо-

ту, которую может выполнять микросхема таймера. Хотя этот способ

более труден, но он допускает существенно больший контроль над

динамиком и создание большинства специальных звуковых эффектов

[2.2.8] основывается на нем.


Высокий уровень.


Оператор Бейсика SOUND используется для генерации тона в широ-

ком диапазоне частот и длительностей. Частота дается в герцах (от

37 до 32767), а длительность в импульсах счетчика времени суток

BIOS (от 0 до 65535), причем в секунду происходит 18.2 импульса.

SOUND 440,91 воспроизводит ноту A в течение 5 секунд (5*18.2).

Частоты первой октавы, начиная с ноты C(до) таковы:


C(до) 523.3

D(ре) 587.3

E(ми) 659.3

F(фа) 698.5

G(соль) 784.0

A(ля) 880.0

B(си) 987.7


Частоты на октаву выше можно получить, удваивая эти значения, на

две октавы выше - еще раз удваивая частоты. И наоборот, частоты

на октаву ниже равны приблизительно половине этих значений (хоро-

шо настроенное пианино точно не следует арифметическим интерва-

лам).

Благодаря своему генератору звука [2.2.1] PCjr может использо-

вать оператор SOUND для трех независимых каналов звука, причем

может управляться громкость каждого из них. В этом случае формат

оператора: SOUND частота, длительность, громкость, канал. Гром-

кость может меняться от 0 до 15, по умолчанию 8. Номер канала

может меняться от 0 до 2, по умолчанию 0. Поскольку PCjr может

использовать возможности многоголосия и контроля звука только для

внешнего динамика, то надо сначала разрешить этот динамик. Это

делается с помощью оператора SOUND ON. SOUND OFF передает конт-

роль внутреннему динамику. Чтобы сыграть аккорд D-минор (ре-ми-

нор) (D-F-A) с малой громкостью, напишите:


100 SOUND ON 'разрешение внешнего динамика

110 SOUND 587,50,3,0 'нота ре

120 SOUND 699,50,3,1 'нота фа

130 SOUND 880,50,3,1 'нота ля



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


Генерация звука с помощью адаптера интерфейса с периферией

8255 состоит во включении и выключении с желаемой частотой бита