Программирование Adlib/SoundBlaster ЧМ Синтезатор Версия 2.0 ( 24 февраля 1992 ) Авторское Право 1991 (c), 1992 Jeffrey S. Lee jlee@smylex.uucp Все числа в шестнадцетеричной системе, если специально не оговоренно. Часть 1 - Порты звуковой карты Звуковая плата программируется посылкой данных во внутренние регистры через два порта ввода/вывода: 0x0388 - порт Адреса / Состояния (R/W) 0x0389 - порт Данных (W/O) Sound Blaster Pro воспроизводит стерео музыку, обращение к каналам происходит также, но базовый адрес для левого канала 0x220, правого 0x222. Sound Blaster совместим с Adlib. Через 0x388 и 0x389 порты происходит вывод музыки через оба динамика. В звуковой плате 244 внутренних регистра (01-F5). Для того чтобы записать значение в регистр: - запишите номер регистра в порт адреса; - запишите значение в регистр данных. После записи порт адреса надо 6 раз считать из него, перед посылкой данных в регистр данных. После записи данных 30 раз, прежде, чем можно будет снова продолжить программирование карты. В руководстве по Adlib сказано, что ожидать надо 3.3 микросекунды для адреса, и 23 мкс для данных. Регистры звуковой карты только на запись. Для того того чтобы прочитать байт состояния звуковой карты, просто прочитайте порт 0x388. Байт состояния имеет следующую структуру: 7 6 5 4 3 2 1 0 +---------+--------+--------+------+------+------+------+------+ | Оба | таймер | таймер | Неиспользуется | | таймера | 1 | 2 | | +---------+--------+--------+------+------+------+------+------+ Бит 7 - установлен если оба таймера истекли. 6 - установлен если 1 таймер установлен. 5 - установлен если 2 таймер установлен. Часть 2 - Регистры В этой таблице приведены функции каждого регистра в звуковой карты. Регистры объясняются после таблицы. Не приведенные регистры неиспользуются. Адрес Функци ------- ---------------------------------------------------- 01 Тест LSI / Выбор формы волны 02 Таймер 1 03 Таймер 2 04 Флаги управления Таймера 08 Речевой режим синтеза / Способ кодирования нот 20. .35 Тремоло / Вибрато / Постоянный уровень / Изменение длительности / Умножение частоты 40. .55 Изменение уровня / Уровень сигнала ( громкость ) 60. .75 Атака / Спад после атаки 80. .95 Постояный уровень / Затухание A0.. A8 Частота ( 8 младших битов ) B0.. B8 Включить ноту / Октава / Частота ( 2 старших бита ) BD Глубина тремоло / вибрато / контроль ритма C0.. C8 Величина обратной связи / режим обьединения цепей E0.. F5 Форма волны Группы из двадцати двух регистров ( 20-35, 40-55, и т.д.. ) содержат информацию о 9 инструментах. Информация о каждом инструменте состоит из байта описания цепи 1, и байта описания цепи 2. Следующая таблица показывает смещения в пределах каждой группы регистров для каждой цепи. Канал 1 2 3 4 5 6 7 8 9 Цепь 1 00 01 02 08 09 0A 10 11 12 Цепь 2 03 04 05 0B 0C 0D 13 14 15 Таким образом, адрес байта атака/спад для канала 3 - 62 для цепи 1, и 65 для цепи 2. ( Адрес второй цепи - всегда равняется адрес первой цепи плюс три ). Чтобы иллюстрировать эту связь, приведены адреса необходимые чтобы управлять каналом 5: 29 - Цепь 1 Тремоло 2C - Цепь 2 Тремоло 49 - Цепь 1 Уровень 4C - Цепь 2 Уровень 69 - Цепь 1 Атака 6C - Цепь 2 Атака 89 - Цепь 1 Затухание 8C - Цепь 2 Затухание A4 - Частота ( 8 младших битов ) B4 - Включить ноту / Октава / Частота ( 2 старших бита ) C4 - Величина обратной связи / режим обьединения цепей E9 - Цепь 1 Форма Волны EC - Цепь 2 Форма Волны Пояснения работы регистров карты Байт 01 - Этот байт обычно используется чтобы проверять LSI устройство. Все биты обычно установлены в ноль. Бит 5 разрешает выбор формы волны 0 - синусоидальная, 1 - определяется E0-F5 Байт 02 - Таймер 1. Если таймер 1 доступен, значение в этом регистре будет увеличиваться пока не переполняется. После переполнения, звуковая плата будет вызывать прерывание таймера ( int 08 ) и установит биты 7 и 6 в байте состояния. Счетчик этого таймера увеличивается каждые 80 микросекунд. Байт 03 - Таймер 2. Если таймер 1 доступен, значение в этом регистре будет увеличиваться пока не переполняется. После переполнения, звуковая плата будет вызывать прерывание таймера ( int 08 ) и установит биты 7 и 6 в байте состояния. Счетчик этого таймера увеличивается каждые 320 микросекунд. Байт 04 - Служебный байт таймера 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | IRQ | T1 | T2 | Неиспользуется | T2 | T1 | | RST | MSK | MSK | | CTL | CTL | +-----+-----+-----+-----+-----+-----+-----+-----+ сброс маски старт таймеров таймера таймеров Бит 7 - Сброс флажков таймеров 1 & 2. При этом все другие биты игнорируются. Бит 6 - Маска таймера 1. При установлен, то бит 0 игнорируется. Бит 5 - Маска таймера 2. При установлен, то бит 1 игнорируется. Бит 1 - Когда очищен, то таймер 2 не работает. Когда установлен, значение из байта 03 загружаетс в таймер 2, и начинается увеличиваться. Бит 0 - Когда очищен, то таймер 1 не работает. Когда установлен, значение из байта 02 загружаетс в таймер 1, и начинается увеличиваться. Байт 08 - Речевой режим синтеза / Способ кодирования нот. 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | CSM | Key | Неиспользуется | | Sel | Spl | | +-----+-----+-----+-----+-----+-----+-----+-----+ Бит 7 - Когда установлен, выбирает композитный режим синтеза речи ( все KEY-ON биты должен быть очищены ). Когда сброшен, то выбор FM режима. Бит 6 - Выбор режима кодирования нот. Байты 20-35 - Тремоло / Вибрато / Постоянный уровень / Изменение длительности / Умножение частоты 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | Amp | Vib | EG | KSR | Умножение частоты | | Mod | | Typ | | | +-----+-----+-----+-----+-----+-----+-----+-----+ "Тремоло" Постоянный уровень "Вибрато" Изменение длительности Бит 7 - Применяется "тремоло" когда установлено; глубина управляется флажком AM-Depth по адресу BD. Бит 6 - Применяется "вибрато" когда установлено; глубина управляется флажком VIB-depth по адресу BD. Бит 5 - Если установлен, постоянный уровень сигнала поддерживаетс пока не отпущено; когда сброшен, звук начинается без задержки после постоянной фазы. Бит 4 - Когда установлен, то включает режим изменения длительности сигнала с ростом частоты Бит 3-0 - Эти биты указывают какая гармоника будет воспроизводить звук ( или модуляцию ) в отношении частоты воспроизводимого звука ( коэффициент умножения частоты ) 0 - на одну октаву ниже 1 - в определеной частоте звука 2 - на одна октаву выше 3 - на октаву и пятый выше 4 - Две октавы выше 5 - Две октавы и мажор треть выше 6 - Две октавы и пятый выше 7 - Две октавы и минор седьмой выше 8 - Три октавы выше 9 - Три октавы и мажор секунда выше A - три октавы и мажор треть выше B - " """ """ C - три октавы и пятый выше D - " """ " " E - три октавы и мажор седьмой выше F - " """ """ Байты 40-55 - Изменение уровня / Уровень сигнала ( громкость ) 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | Изменение | Общий Уровень | | Уровня | 24 12 6 3 1.5 .75 | < - dB +-----+-----+-----+-----+-----+-----+-----+-----+ Биты 7-6 - устанавливают как будет уменьшатся выходной уровень с ростом частоты: 00 - нет изменени 10 - 1.5 DB/8ve 01 - 3 DB/8ve 11 - 6 DB/8ve Биты 5-0 - контролирует общий выходной уровень цепи. Когда все биты очищены то самый громкий; Когда все установлены то самый тихий. Определяют уровень сигнала. Когда цепь включена аддитивно или является генератором несущей, они устанавливают громкость звучания. Если цепь используется для генерации модулирующего сигнала, эти разряды задают глубину модуляции. Учтите, что громкость от их содержимого зависит не линейно. При увеличении на 1 уменьшается на 0.75 DB Байты 60-75 - Атака / Спад после атаки 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | Скорость | Скорость | | Атаки | Спада | +-----+-----+-----+-----+-----+-----+-----+-----+ Биты 7-4 - скорость атаки. 0 - низкая, F - быстрая. Биты 3-0 - скорость спада. 0 - низкая, F - быстрая. Байты 80-95 - Постоянный уровень / Затухание 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | Постоянный Уровень | Скорость | | 24 12 6 3 | затухания | +-----+-----+-----+-----+-----+-----+-----+-----+ Биты 7-4 - постоянный Уровень. 0 самый громокий, F самый тихий. Биты 3-0 - Скорость затухания. 0 - медленно, F самый быстрый. Байты A0-B8 - Частота ( 8 младших битов ) / Включить ноту / Октава / Частота ( 2 старших бита ) 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | Восемь младщих битов частоты | (A0-A8) | | +-----+-----+-----+-----+-----+-----+-----+-----+ 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+------+ | Неисполь- | Вкл | Октава |Два старших | (B0-B8) | зуется | Ноту| |бита частоты| +-----+-----+-----+-----+-----+-----+-----+------+ Эти регистры задают ноту и октаву для каждого из девяти голосовых каналов. Отметим, что для работы с синтезатором достаточно знать частоты нот в пределах одной октавы. Бита 5 - Канал звучит когда установлен. Биты 4-2 - Октава (0-7). 0 низкая, 7 высокая. Биты 1-0 - Старшие биты частоты. Кодирование нот в октаве 4: Код Частота Нота 16B 277.2 C(#)(до#) 181 293.7 D (ре) 198 311.1 D(#)(ре#) 1B0 329.6 E (ми) 1CA 349.2 F (фа) 1E5 370.0 F(#)(фа#) 202 392.0 G(соль) 220 415.3 G(#)(соль#) 241 440.0 A(ля) 263 466.2 A(#)(ля#) 287 493.9 B(си) 2AE 523.3 C(до) Байты C0-C8 - Величина обратной связи / режим обьединения цепей 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | Неиспользуется | Глубина | Alg | | | Обратной Связи | | +-----+-----+-----+-----+-----+-----+-----+-----+ Режим обьединения сигналов колебательных цепей. Биты 3-1 - Величина обратной связи. Если все три бита = 0, то обратной связи нет. При значениях 1-7, цепь 1 будет посылать часть вывода обратно самостоятельно. 1 меньше 7 - максимум. Бита 0 - Если = 0, то цепь 1 модулирует цепь 2. В этом случае, только цепь 2 воспроизводит звук. Если = 1, обе цепи воспроизводят звук. Комплексные звуки легко создаются, если = 0. Байт BD - Глубина тремоло / вибрато / контроль ритма 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | AM | Vib | Rhy | BD | SD | TOM | Top | HH | | Dep | Dep | Ena | | | | Cym | | +-----+-----+-----+-----+-----+-----+-----+-----+ Глубина режим Малый барабан Тарелки тремоло ударных включить включить Глубина Большой Там-там вибрато барабан включить включить Цимбалы включить Бит 7 - задает глубину "тремоло" =1 - 4.8db, =0 - 1db. Бит 6 - определяет глубину "вибрато" =1 - 14%, =0 - 7%. Бит 5 - включает режим мелодии (0) ( 9 голосов ) или ударных (1) ( 6 голосов ). Если установлен режим ударных используютс биты с 4 по 0. Смещение регистров колебательных цепей в этом режиме такое: Канал 1 2 3 4 5 Большой Малай Там-там Цимбалы Тарелки барабан барабан Цепь 1 00 01 02 08 09 0A 14 12 15 11 Цепь 2 03 04 05 0B 0C 0D Байты E0-F5 - Выбор Формы Волны 7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+------+ | Неиспользуется | Выбор формы| | | волны | +-----+-----+-----+-----+-----+-----+-----+------+ Биты 1-0 - Когда бит 5 регистра 01 установлен, выходна форма волны будут искажаться согласно форме волны обозначенной этими двумя битами. Мы будем пробовать изображать схематически их здесь, но это трудно ___ ___ ___ ___ _ _ / \ / \ / \ / \ / | / | /_____\_______ /_____\_____ /_____\/_____\ /__|___/__|___ \ / \___/ 00 01 10 11 Обнаружение Звуковой Платы Согласно руководству AdLib, "официальный" метод обнаружения Adlib 1) Сбросьте оба таймера записав 60h в регистр 4. 2) Разрешите прерывания записав 80h в регистр 4. 3) Прочитайте регистр состояния ( порт 388-ой ). Сохраните результат. 4) Запишите FFh в регистр 2 ( Таймер 1 ). 5) Запустите таймер 1 записав 21h в регистр 4. 6) Сделайте задержку на 80 микросекунд. 7) Читайте регистр состояния ( порт 388-ой ). Сохраните результат. 8) Сбросьте и таймеры и прерывания ( см. шаги 1 и 2 ). 9) Проверите сохраненные результаты шагов 3 и 7 и AND их с E0h. Результат шага 3 должен быть 00h, и результат шага 7 должен быть C0h. Если это правильно, то AdLib-совместимая плата устанавлена в ПЭВМ. Другой метод: PROC Detectadlib ;proc to detect adlib stc ;set the carry flag (default) pusha ;preserve regs mov dx,0388h ;use the code posted by lee in al,dx ;someone else suggested it... cmp al,0 ;seems to work je @@there ;adlib present, clear carry flag cmp al,6 ;adlib not present if al<>0 OR 6 jne @@carryon ;and again... ; @@there: clc ;clear cf, adlib is there @@carryon: popa ;restore our regs ret ;return ENDP ;end of detect adlib proc Официальный метод AdlibAddr dw 0388h WriteFM PROC NEAR push ax push cx push dx xchg al,ah mov dx, cs:AdlibAddr out dx, al mov cx,7 call FMwait inc dx mov al,ah out dx,al dec dx mov cx,30 call FMwait pop dx pop cx pop ax ret FMwait: in al,dx loop FMwait ret WriteFM ENDP ;----------------------------------------------------------------------------- ;- Check for FM chip, returns CF = 0 if found, or CF = 1 if not -------------- ;----------------------------------------------------------------------------- TestFMchip proc far mov ax, 00100h Call WriteFM mov ax, 00480h Call WriteFM mov dx, cs:AdlibAddr in al, dx mov cl, al mov ax, 002FFh Call WriteFM mov ax, 00421h Call WriteFM mov dx, cs:AdlibAddr mov cx, 100 call FMwait mov ch, al mov ax, 00460h Call WriteFM mov al, 80h Call WriteFM and cl, 0E0h cmp cl, 0 jne No_FMchip and ch, 0E0h cmp ch, 0C0h jne No_FMchip popa clc ret No_FMchip: popa stc ret TestFMchip endp Примечания переводчика Данный документ составлен Анисимовым С.Ю. 09/1995 Данными для составления этого документа послужила информация из различных источников. Поэтому автор не несет ответственность за неверную информацию, и за повреждения техники и тел при использовании этого документа. С наилучшими пожеланиями, для всех любителей программировать Adlib ! Vale !