# 10. Звук ## 10.1 Общие сведения > Документ описывает звуковую подсистему платы **Sp2000** и более новых моделей. > Информация о Sprinter-97 не рассматривается. Звуковая подсистема Sprinter Sp2000 включает три компонента: | Компонент | Тип | Описание | |-----------|-----|----------| | GM80C760 (AY-3-8910 совм.) | Музыкальный сопроцессор | 3 голоса + шум + огибающая, эмуляция в ППЛМ | | COVOX | 8-битный ЦАП | Прямой вывод сэмплов через порт `#FB`/`#4F` | | CBL (COVOX-Blaster) | COVOX с буфером | 256 байт буфера, прерывания, разные режимы | Весь звук выводится через **16-битный ЦАП TDA1543** (двухканальный, стерео). Реально используется 10 бит для одновременного смешивания 8-bit COVOX и AY [IvanMak.txt:632–634]. **На Sp2000 все три компонента присутствуют в основной прошивке ППЛМ.** CBL включается через порт `#4E` (бит 7 = 1). При выключенном CBL (бит 7 = 0) работает обычный 8-bit COVOX [IvanMak.txt:662–666]. ## 10.2 GM80C760 (AY-3-8910) ### 10.2.1 Реализация AY-функция реализована на микросхеме **GM80C760** (ППЛМ ALTERA EP1K30), AY-3-8910/8912 совместимая. Это не отдельная дискретная микросхема [IvanMak.txt:636–637]. На EP1K30 (Sp2000) реализована **3-я версия** AY. Включает три голоса, шум и генератор огибающей (envelope). В формирователе огибающей обнаружена небольшая ошибка, детали не документированы [IvanMak.txt:224–229], [12-bugs.md §11.2]. ### 10.2.2 Порты | Порт | Назначение | |------|-----------| | `#BFFD` | AY-8910 — запись номера регистра (address) | | `#FFFD` | AY-8910 — чтение/запись данных регистра (data) | Внутренние номера в карте дешифратора ППЛМ: `90h` (`#BFFD`), `91h` (`#FFFD`) [IvanMak.txt:1298–1299]. ### 10.2.3 Программирование Программирование — **стандартное для AY-3-8910/8912** [IvanMak.txt:636–637]: ```asm ; Установить регистр AY LD BC, #BFFD OUT (C), A ; A = номер регистра (0..15) LD BC, #FFFD OUT (C), A ; A = значение ; Прочитать регистр AY (3-я версия) LD BC, #BFFD OUT (C), A ; A = номер регистра LD BC, #FFFD IN A, (C) ; читать данные ``` **Регистры AY-3-8910** (стандартные): | № | Назначение | |:-:|-----------| | 0 | Частота канала A (младший байт) | | 1 | Частота канала A (старшие 4 бита) | | 2 | Частота канала B (младший байт) | | 3 | Частота канала B (старшие 4 бита) | | 4 | Частота канала C (младший байт) | | 5 | Частота канала C (старшие 4 бита) | | 6 | Период шума | | 7 | Микшер (включение каналов и шума) | | 8 | Громкость A | | 9 | Громкость B | | 10 | Громкость C | | 11 | Период огибающей (младший байт) | | 12 | Период огибающей (старшие 8 бит) | | 13 | Форма огибающей | | 14 | Порт I/O A (не используется на Sprinter) | | 15 | Порт I/O B (не используется на Sprinter) | **Стерео:** AY имеет два выходных канала, но в стандартной конфигурации Sprinter оба канала получают монофонический сигнал. --- ## 10.3 COVOX (8-бит) ### 10.3.1 Порты | Порт | Назначение | |------|-----------| | `#FB` | COVOX data (он же порт включения КЭШ-ОЗУ по IN) | | `#4F` | COVOX data (альтернативный адрес) | [IvanMak.txt:642, 1347] ### 10.3.2 Программирование Простейший вывод сэмплов — последовательная запись байтов в порт `#FB` или `#4F`: ```asm ; Цикл вывода сэмплов (8 бит, моно) LD HL, sample_data LD BC, sample_length loop: LD A, (HL) OUT (#FB), A INC HL DEC BC LD A, B OR C JR NZ, loop ``` ### 10.3.3 Конфликт с Fast RAM (КЭШ-ОЗУ) Порт `#FB` используется **для двух целей**: - `OUT (#FB), A` — запись в COVOX - `IN A, (#FB)` — включение КЭШ-ОЗУ Если КЭШ-ОЗУ включено, запись в `#FB` уходит в кэш, а не в COVOX. Перед работой с COVOX кэш нужно отключать: `IN A, (#7B)` [IvanMak.txt:850–851], [12-bugs.md §11.4]. --- ## 10.4 COVOX-Blaster (CBL) ### 10.4.1 Общее описание **CBL (COVOX-Blaster)** — COVOX с буферным ОЗУ на **256 байт**. Позволяет выводить звук поблочно, освобождая процессор для другой работы [IvanMak.txt:647], [Parinov.txt:688]. ### 10.4.2 Порт управления `#4E` **Порт `#4E` — 16-битный! Только через `OUT (C),A`** (с `LD BC,004Eh`) [Parinov.txt:692–693]. > **Примечание:** IvanMak.txt упоминает его как 8-битный, но Parinov.txt явно > указывает 16-битный доступ. Современный код использует `OUT (C),A`. **Биты порта `#4E`** [Parinov.txt:695–698]: | Бит | Мнемоника | Назначение | |-----|-----------|-----------| | 7 | **CBL_ON** | 1 = CBL включён, 0 = обычный COVOX | | 6 | **STEREO** | 1 = стерео, 0 = моно | | 5 | **16BIT** | 1 = 16-битные сэмплы, 0 = 8-битные | | 4 | **IRQ_EN** | 1 = включить прерывания от CBL | | 3–0 | **FREQ** | Частота дискретизации (см. таблицу) | ### 10.4.3 Частоты дискретизации [Parinov.txt:700–718]: | Код | Частота | Примечание | |:---:|---------|-----------| | 0 | 16 kHz | старые режимы, **НЕ ИСПОЛЬЗОВАТЬ** | | 1 | 22 kHz | старые режимы, **НЕ ИСПОЛЬЗОВАТЬ** | | 2–7 | — | зарезервировано | | **8** | **7.8125 kHz** | mono/stereo, 8/16-bit | | **9** | **10.9375 kHz** | mono/stereo, 8/16-bit | | **A** | **15.625 kHz** | mono/stereo, 8/16-bit | | **B** | **21.875 kHz** | mono/stereo, 8/16-bit | | **C** | **31.25 kHz** | mono/stereo, 8/16-bit | | **D** | **43.75 kHz** | mono/stereo, 8/16-bit | | **E** | **54.6875 kHz** | mono/stereo, 8/16-bit | | **F** | **109.375 kHz** | mono/stereo, 8/16-bit | > **Важно:** коды 0 и 1 — старые режимы из первых прошивок, несовместимы с > новыми режимами (8–F). Использовать только коды 8–F. ### 10.4.4 Режимы и формат данных [Parinov.txt:767–783]: | Режим | Нулевой уровень | Размер блока | Формат данных | |-------|:---------------:|:------------:|--------------| | mono 8-bit | `80h` | 128 байт | `DB 80h, 81h, 7Fh, ...` | | mono 16-bit | `0000h` | 256 байт | `DW 0, 1000, -1000, ...` | | stereo 8-bit | `80h,80h` | 128 байт | `DB 80h,80h, 81h,80h, ...` (L, R чередуются) | | stereo 16-bit | `0000h,0000h` | 256 байт | `DW 0,0, 1000,0, ...` (L, R чередуются) | Формат данных выбран так, чтобы WAV-файлы можно было пересылать в CBL простой `OTIR` [Parinov.txt:791]. ### 10.4.5 Буфер CBL и механизм банок CBL имеет буферное ОЗУ на **256 байт**, организованное как кольцевой буфер [Parinov.txt:758–760]: - Счётчик CBL считает **«назад»** — из-за особенности команды `OUTI`, где `B` уменьшается и попадает на A15..A8. - Для 8-битных режимов буфер условно разбит на **две банки по 128 байт**. - Для 16-битного режима блок = **256 байт** (весь буфер). **Механизм работы:** 1. Процессор записывает блок данных (128 байт для 8-бит, 256 байт для 16-бит) в буфер CBL. 2. Аппаратный счётчик CBL автоматически считывает данные из буфера и отправляет в ЦАП на заданной частоте. 3. Бит 7 порта `#FE` указывает, какая банка сейчас выводится в ЦАП. 4. Когда банка переключается — CBL запрашивает следующую порцию данных (через прерывание или polling). 5. Запрос данных возникает для **каждых 128 байт (256 в 16-битном режиме)**. ### 10.4.6 Порт статуса `#FE` **Бит 7 порта `#FE`** — запрос данных для CBL [Parinov.txt:720–724]: | Бит | Назначение | |-----|-----------| | 7 | **CBL data request** — 1 = CBL запрашивает новую порцию данных | | 5 | **Frame sync** — кадровый импульс (4 мс длиной, 20 мс период) | > **Примечание:** В MAME при выключенном CBL бит 7 порта #FE всегда = 1. > Это следует учитывать при разработке обработчика прерываний > [`im2_isr_design.md:26–31`]. **Противоречие** [08-io.md §8.3]: - IvanMak.txt описывает бит 7 как старший бит счётчика CBL для polling (определение, какая половина буфера выводится). - Parinov.txt описывает его как запрос прерывания. - Оба описывают одну физическую линию, но в разных режимах (polling vs interrupt). ### 10.4.7 Прерывания и IM2 - При включённых прерываниях CBL (бит 4 порта `#4E` = 1) необходим **режим IM 2**. - Если остаться на IM1, DOS-процедура прерываний будет вызываться слишком часто, что вызовет тормоза на высоких частотах [Parinov.txt:762–764]. - **Вектор прерывания CBL — `#FF`** (как и у клавиатуры, и у кадрового). Отличать — по биту 7 порта `#FE` [`sprinterIntLib.asm:24–26`]. **Обработчик прерываний на IM2:** ```asm ; Проверка источника IN A, (#FE) RLCA ; бит 7 → CF JR NC, not_cbl ; не CBL — на другой обработчик ; CBL запрашивает данные LD BC, 804Fh ; B = 128 (счётчик), C = 4Fh (порт CBL data) LD HL, next_block OTIR ; вывести 128 байт в буфер CBL ... ``` ### 10.4.8 Запись данных в CBL **Способ 1: OTIR/OUTI через порт `#4F`** ```asm LD BC, 804Fh ; B = 128 (счётчик), C = #4F (CBL data) LD HL, data_block OTIR ; вывести 128 байт ``` **Способ 2: через страницу ОЗУ `#FD` с акселератором** Страница `#FD`, отображённая в окно `#C000`, аппаратно связана с буфером CBL. Для 8-битного режима — записать 128 байт; для 16-битного — 256 байт [Parinov.txt:727–731]. ```asm ; Запись блока данных в CBL через страницу #FD с акселератором IN A, (#E2) ; сохранить текущую страницу W3 LD (.save_page), A LD A, #FD OUT (#E2), A ; W3 = страница CBL LD DE, #C000 ; приёмник (CBL buffer) LD B, 0 ; B = 0 → 256 байт (или 128 для 8-bit) LD D,D ; ACC_ON: включить акселератор LD L,L ; ACC_CopyBlock_Horizontal LD A, (HL) ; загрузить байт в буфер акселератора LD (DE), A ; записать в CBL LD B,B ; ACC_OFF: выключить акселератор LD A, (.save_page) OUT (#E2), A ; восстановить страницу ``` ### 10.4.9 Полный пример Из `docs/samples/Пример для CBL.asm` [sprinterIntLib.asm]: ```asm ; Инициализация IM2 LD A, #BE LD I, A ; таблица векторов по #BE00 IM 2 ; Вектор прерывания CBL = #BEFF ; (Interrupt_Vector OR 0FFh) ; Включение CBL LD BC, #4E LD A, %10011000b ; bit7=1 CBL on, bit4=1 IRQ en, bits3-0=1000 = 7.8125 kHz OUT (C), A ; В ISR: ; IN A, (#FE) ; RLCA ; JR NC, .NoSound ; ... копировать 128 байт через страницу #FD с акселератором ; После проигрывания: ; Установить NumberPage=2, подождать HALT ; Выключение CBL: LD BC, #4E LD A, 0 OUT (C), A ``` ### 10.4.10 Известные проблемы 1. **CBL vs Fast RAM:** порт `#FB` используется и для COVOX/CBL, и для включения КЭШ-ОЗУ (см. §10.3.3). 2. **Щелчок перед первым звуком:** известная проблема при старте CBL [`TODO.md:263`]. 3. **Помехи при движении мыши:** часть тиков прерываний, обслуживающих CBL-насос, уходит на обслуживание мыши [`TODO.md:270–277`]. 4. **Порт #4E — 8-бит vs 16-бит:** IvanMak подразумевает 8-битный, Parinov требует 16-битный `OUT (C),A` (см. §10.4.2). 5. **MAME: бит 7 порта #FE = 1 при выключенном CBL:** может вызвать ложные срабатывания обработчика (см. §10.4.6). --- ## 10.5 Бипер Стандартный Spectrum-бипер — бит 3 (в некоторых конфигурациях бит 5) порта `#FE`. Выведен через ту же схему TDA1543, что COVOX и AY [IvanMak.txt:639–640]. ```asm ; Включить бипер LD A, %00001000 ; бит 3 = 1 OUT (#FE), A ; Выключить бипер LD A, %00000000 ; бит 3 = 0 OUT (#FE), A ``` --- ## 10.6 SSC (Sprinter Sound Card) Разрабатывалась, но **не реализована** ни в одной прошивке Sp2000 из-за большого объёма ПЛМ [IvanMak.txt:763–772]. Параметры проекта: - 2 канала - 16 восьмибитных голосов - 256-байтные Wave-таблицы для каждого голоса - 8-битный регулятор амплитуды --- ## 10.7 Кросс-ссылки - Порты звука: `11-ports.md` - Баги AY и CBL: `12-bugs.md` - Fast RAM и конфликт с COVOX: `04-memory.md §4.6` - 08-io.md (остальной ввод-вывод): `08-io.md`