docs: справочники по железу Sprinter + правка gfx_scroll_h
- docs/new/ — сводные справочники (архитектура, BIOS, DSS, память, графика, акселератор, IRQ, порты, ввод, звук, известные баги); - docs/Original/ — первоисточники, из которых они собраны (BIOS, Estex DSS, мануалы, описание акселератора), + Форум.doc/.docx в reference; - libbgi/common/gfx_scroll_h.c — обход бага скролла при ширине >256 (правка автора: шаг банды 255 и продвижение указателей на cw; старый вариант с 256 оставлен закомментированным с TODO); - удалён applications/PoP/roomtest/hang_variants.png — рабочая раскладка из разбора позы виса, в репозитории ей не место. Большие архивы (docs/extra ~568 МБ, docs/sources с вложенными git-репо ~68 МБ) в коммит НЕ включены — см. обсуждение. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,377 @@
|
||||
# 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`
|
||||
Reference in New Issue
Block a user