532 lines
36 KiB
C
532 lines
36 KiB
C
/**
|
||
* @file tsconf.h
|
||
* @brief Полный справочник регистров TSConfig (TSL FPGA-ускоритель ZX Spectrum)
|
||
* @version 2.0
|
||
*
|
||
* Самодостаточная библиотека: зависит только от types.h.
|
||
* Подходит для любого TSConfig-проекта на SDCC Z80.
|
||
*
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
* АРХИТЕКТУРА ПОРТОВ
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
*
|
||
* Все порты TSConfig адресуются по схеме: (REG_NUM << 8) | 0xAF
|
||
* Запись: OUT (C),A где BC = порт.
|
||
*
|
||
* На ASM:
|
||
* LD BC, TSCONF_PORT_SYSCONFIG ; BC = 0x20AF
|
||
* LD A, TSCONF_CPU_14MHZ
|
||
* OUT (C), A
|
||
*
|
||
* На C:
|
||
* tsconf_out(TSCONF_PORT_SYSCONFIG, TSCONF_CPU_14MHZ);
|
||
*
|
||
* Макросы-обёртки (конец файла) упрощают типичные операции:
|
||
* tsconf_set_cpu(TSCONF_CPU_14MHZ);
|
||
* tsconf_set_border(1);
|
||
* tsconf_set_frame_int(100, 0);
|
||
*
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
* ТАЙМИНГИ TV-РЕЖИМА (Pentagon-128)
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
*
|
||
* Строк в кадре: 320 (0–319)
|
||
* Строки 0–31: вертикальное гашение
|
||
* Строки 32–319: видимая область (бордер + пиксели)
|
||
*
|
||
* Пикселей в строке: 448 (7 МГц), = 224 T-states при 3.5 МГц
|
||
* Пиксели 0–87: горизонтальное гашение
|
||
* Пиксели 88–447: видимая область
|
||
*
|
||
* T-states в кадре: 320 × 224 = 71680 T
|
||
*
|
||
* ══════════════════════════════════════════════════════════════════════
|
||
* ПРЕРЫВАНИЯ (IM2)
|
||
* ══════════════════════════════════════════════════════════════════════
|
||
*
|
||
* Три источника, каждый выставляет свой вектор на шину данных:
|
||
* FRAME (#FF, приоритет 0) — совпадение растровых счётчиков
|
||
* с регистрами HSINT/VSINT
|
||
* LINE (#FD, приоритет 1) — каждая строка при HCNT = 0
|
||
* DMA (#FB, приоритет 2) — конец DMA-транзакции
|
||
*
|
||
* HSINT = HCNT[8:1]: горизонтальная позиция (0–223). >223 = выкл.
|
||
* VSINTL/VSINTH = VCNT[8:0]: вертикальная строка (0–319). >319 = выкл.
|
||
*
|
||
* VINT_INC[3:0] в VSINTH: автоинкремент VCNT после каждого FRAME-INT
|
||
* (позволяет менять строку прерывания без записи в порты).
|
||
*
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
* ВИДЕО
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
*
|
||
* VM[1:0]: 00=ZX (256x192, атрибуты), 01=16c, 10=256c, 11=txt
|
||
* RRES[1:0]: 00=256x192, 01=320x200, 10=320x240, 11=360x288
|
||
*
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
* DMA
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
*
|
||
* Адрес = 22-бит: [X(8)][H(6)][L(7)][0] — младший бит всегда 0.
|
||
*
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
* ПРИМЕР (минимальный)
|
||
* ═══════════════════════════════════════════════════════════════════
|
||
*
|
||
* #include "tsconf.h"
|
||
*
|
||
* void demo(void) {
|
||
* tsconf_set_cpu(TSCONF_CPU_14MHZ); // 14 МГц
|
||
* tsconf_set_border(2); // красный бордюр
|
||
* tsconf_set_vconfig(TSCONF_VM_ZX // ZX-режим
|
||
* | TSCONF_RRES_256x192); // 256x192
|
||
* tsconf_set_frame_int(100, 0); // INT на строке 100
|
||
* tsconf_set_intmask(TSCONF_INT_FRAME); // только FRAME
|
||
* tsconf_set_cpu(TSCONF_CPU_3_5MHZ); // вернуть 3.5
|
||
* }
|
||
*/
|
||
|
||
#ifndef TSCONF_H
|
||
#define TSCONF_H
|
||
|
||
#include "types.h"
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* Макрос формирования адреса порта
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT(reg) (((uint16_t)(reg) << 8) | 0xAF)
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* ВИДЕО — VConfig (#00AF)
|
||
* W: RRES[1:0] | - | NOGFX | NOTSU | GFXOVR* | FT_EN** | VM[1:0]
|
||
* R: - | PWR_UP | - | FDRVER | VDVER[2:0]
|
||
* * только VDAC, ** только VDAC2. Сброс: 0x00
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_VCONFIG TSCONF_PORT(0x00)
|
||
|
||
/* VM[1:0] — видеорежим */
|
||
#define TSCONF_VM_ZX 0x00 /* ZX-Spectrum, 256×192, атрибуты */
|
||
#define TSCONF_VM_16C 0x01 /* 16 цветов, 4 бита/пиксель */
|
||
#define TSCONF_VM_256C 0x02 /* 256 цветов, 8 бит/пиксель */
|
||
#define TSCONF_VM_TXT 0x03 /* Текстовый режим */
|
||
#define TSCONF_VM_MASK 0x03
|
||
|
||
/* FT_EN, GFXOVR, NOTSU, NOGFX */
|
||
#define TSCONF_VC_FT_EN 0x04 /* FT812 enable (VDAC2) */
|
||
#define TSCONF_VC_GFXOVR 0x08 /* GFX поверх TSU (VDAC) */
|
||
#define TSCONF_VC_NOTSU 0x10 /* Отключить TSU-графику */
|
||
#define TSCONF_VC_NOGFX 0x20 /* Отключить основную графику */
|
||
|
||
/* RRES[1:0] — разрешение экрана */
|
||
#define TSCONF_RRES_256x192 (0x00 << 6)
|
||
#define TSCONF_RRES_320x200 (0x01 << 6)
|
||
#define TSCONF_RRES_320x240 (0x02 << 6)
|
||
#define TSCONF_RRES_360x288 (0x03 << 6)
|
||
#define TSCONF_RRES_MASK (0x03 << 6)
|
||
|
||
/* R: Status (то же адрес #00AF, чтение) */
|
||
#define TSCONF_STATUS_VDVER_MASK 0x07
|
||
#define TSCONF_STATUS_FDRVER 0x10
|
||
#define TSCONF_STATUS_PWR_UP 0x40
|
||
#define TSCONF_VDVER_2BIT_PWM 0x00
|
||
#define TSCONF_VDVER_3BIT 0x01
|
||
#define TSCONF_VDVER_4BIT 0x02
|
||
#define TSCONF_VDVER_5BIT 0x03
|
||
#define TSCONF_VDVER_VDAC2 0x07
|
||
|
||
/* ── VPage (#01AF): адрес видеостраницы RA[21:14] ─────────────────── */
|
||
#define TSCONF_PORT_VPAGE TSCONF_PORT(0x01)
|
||
|
||
/* ── GXOffsL (#02AF), GXOffsH (#03AF): X-смещение графики ─────────── */
|
||
#define TSCONF_PORT_GXOFFSL TSCONF_PORT(0x02) /* XO[7:0] */
|
||
#define TSCONF_PORT_GXOFFSH TSCONF_PORT(0x03) /* бит 0 = XO[8] */
|
||
|
||
/* ── GYOffsL (#04AF), GYOffsH (#05AF): Y-смещение графики ─────────── */
|
||
#define TSCONF_PORT_GYOFFSL TSCONF_PORT(0x04) /* YO[7:0] */
|
||
#define TSCONF_PORT_GYOFFSH TSCONF_PORT(0x05) /* бит 0 = YO[8] */
|
||
|
||
/* ── TSConfig (#06AF): включение tile/sprite движка ────────────────── */
|
||
#define TSCONF_PORT_TSCONFIG TSCONF_PORT(0x06)
|
||
#define TSCONF_TS_EXT 0x01 /* TSU 360×288 (не ZX-Evo) */
|
||
#define TSCONF_T0Z_EN 0x04 /* Тайл [0] виден (плоск. 0) */
|
||
#define TSCONF_T1Z_EN 0x08 /* Тайл [0] виден (плоск. 1) */
|
||
#define TSCONF_T0_EN 0x20 /* Tile-layer 0 enable */
|
||
#define TSCONF_T1_EN 0x40 /* Tile-layer 1 enable */
|
||
#define TSCONF_S_EN 0x80 /* Sprite layers enable */
|
||
|
||
/* ── PalSel (#07AF): выбор палитр ──────────────────────────────────── */
|
||
/* GPAL[7:4] | T0PAL[7:6] | T1PAL[7:6]. Сброс = 0x0F */
|
||
#define TSCONF_PORT_PALSEL TSCONF_PORT(0x07)
|
||
|
||
/* ── Border (#0FAF): цвет бордюра ──────────────────────────────────── */
|
||
#define TSCONF_PORT_BORDER TSCONF_PORT(0x0F)
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* УПРАВЛЕНИЕ ПАМЯТЬЮ
|
||
* ══════════════════════════════════════════════════════════════════════
|
||
* RA[21:14] — номер 16KB-страницы DRAM
|
||
* Page0 = W (write-only), Page1 = W, Page2 = RW, Page3 = RW
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_PAGE0 TSCONF_PORT(0x10) /* окно #0000, W */
|
||
#define TSCONF_PORT_PAGE1 TSCONF_PORT(0x11) /* окно #4000, W */
|
||
#define TSCONF_PORT_PAGE2 TSCONF_PORT(0x12) /* окно #8000, RW */
|
||
#define TSCONF_PORT_PAGE3 TSCONF_PORT(0x13) /* окно #C000, RW */
|
||
|
||
/* ── FMAddr (#14AF): адрес Font Maps ───────────────────────────────── */
|
||
#define TSCONF_PORT_FMADDR TSCONF_PORT(0x14)
|
||
#define TSCONF_FMADDR_EN 0x10 /* бит 4 = FM_EN. Биты 3:0 = A[15:12] */
|
||
|
||
/* ── TMPage (#15AF): страница TileMap ──────────────────────────────── */
|
||
#define TSCONF_PORT_TMPAGE TSCONF_PORT(0x15) /* RA[21:14] */
|
||
|
||
/* ── T0GPage (#16AF): страница графики тайлов плоскости 0 ──────────── */
|
||
#define TSCONF_PORT_T0GPAGE TSCONF_PORT(0x16) /* RA[21:17] */
|
||
|
||
/* ── T1GPage (#17AF): страница графики тайлов плоскости 1 ──────────── */
|
||
#define TSCONF_PORT_T1GPAGE TSCONF_PORT(0x17) /* RA[21:17] */
|
||
|
||
/* ── SGPage (#18AF): страница графики спрайтов ─────────────────────── */
|
||
#define TSCONF_PORT_SGPAGE TSCONF_PORT(0x18) /* RA[21:17] */
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* DMA — адреса источника и назначения
|
||
* Адрес = 22-бит: [X(8)][H(6)][L(7)][0]
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_DMASADDRL TSCONF_PORT(0x19) /* Source RA[7:1] */
|
||
#define TSCONF_PORT_DMASADDRH TSCONF_PORT(0x1A) /* Source RA[13:8] */
|
||
#define TSCONF_PORT_DMASADDRX TSCONF_PORT(0x1B) /* Source RA[21:14] */
|
||
#define TSCONF_PORT_DMADADDRL TSCONF_PORT(0x1C) /* Dest RA[7:1] */
|
||
#define TSCONF_PORT_DMADADDRH TSCONF_PORT(0x1D) /* Dest RA[13:8] */
|
||
#define TSCONF_PORT_DMADADDRX TSCONF_PORT(0x1E) /* Dest RA[21:14] */
|
||
#define TSCONF_PORT_DMAWPDEV TSCONF_PORT(0x25) /* DMA Wait Port Dev */
|
||
#define TSCONF_PORT_DMALEN TSCONF_PORT(0x26) /* Burst Length [7:0] */
|
||
#define TSCONF_PORT_DMACTRL TSCONF_PORT(0x27) /* Ctrl W / Status R */
|
||
#define TSCONF_PORT_DMANUM TSCONF_PORT(0x28) /* Bursts Num [7:0] */
|
||
#define TSCONF_PORT_DMANUMH TSCONF_PORT(0x2C) /* Bursts Num [9:8] */
|
||
#define TSCONF_PORT_DMAWPADDR TSCONF_PORT(0x2D) /* Wait Port Addr */
|
||
|
||
/* DMACtrl W — DDEV[3:0]: режим DMA */
|
||
#define TSCONF_DMA_RAM_RAM 0x09 /* RAM→RAM copy */
|
||
#define TSCONF_DMA_BLT1_RAM 0x89 /* RAM→RAM, пропуск нулей (OPT=1) */
|
||
#define TSCONF_DMA_FILL 0x21 /* Fill: src → dest*N */
|
||
#define TSCONF_DMA_RAM_CRAM 0xA1 /* RAM→CRAM (палитра) */
|
||
#define TSCONF_DMA_SPI_RAM 0x11 /* SPI→RAM */
|
||
#define TSCONF_DMA_RAM_SPI 0x91 /* RAM→SPI */
|
||
#define TSCONF_DMA_IDE_RAM 0x19 /* IDE→RAM */
|
||
#define TSCONF_DMA_RAM_IDE 0x99 /* RAM→IDE */
|
||
#define TSCONF_DMA_FDD_RAM 0x29 /* FDD→RAM */
|
||
#define TSCONF_DMA_RAM_WTP 0xB9 /* RAM→Wait Port */
|
||
#define TSCONF_DMA_WTP_RAM 0x39 /* Wait Port→RAM */
|
||
#define TSCONF_DMA_BLT2_RAM 0x31 /* Блиттер с аддером */
|
||
|
||
/* DMACtrl — флаги */
|
||
#define TSCONF_DMA_ASZ_256 0x00 /* Выравнивание 256 байт */
|
||
#define TSCONF_DMA_ASZ_512 0x04 /* Выравнивание 512 байт */
|
||
#define TSCONF_DMA_D_ALGN 0x08 /* Выравнивание назначения */
|
||
#define TSCONF_DMA_S_ALGN 0x10 /* Выравнивание источника */
|
||
/* R: DMAStatus */
|
||
#define TSCONF_DMA_ACT 0x80 /* DMA активна */
|
||
|
||
/* DMAWPDev */
|
||
#define TSCONF_DMAWP_GLUCLOCK 0x00
|
||
#define TSCONF_DMAWP_COMPORT 0x01
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* СИСТЕМНАЯ КОНФИГУРАЦИЯ
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
|
||
/* ── SysConfig (#20AF): частота CPU и кэш ──────────────────────────── */
|
||
#define TSCONF_PORT_SYSCONFIG TSCONF_PORT(0x20)
|
||
#define TSCONF_CPU_3_5MHZ 0x00
|
||
#define TSCONF_CPU_7MHZ 0x01
|
||
#define TSCONF_CPU_14MHZ 0x02
|
||
#define TSCONF_CPU_MASK 0x03
|
||
#define TSCONF_CACHE_EN 0x04 /* Включить кэш (все 4 окна) */
|
||
|
||
/* ── MemConfig (#21AF) ────────────────────────────────────────────────
|
||
* ROM128: бит 0 = то же что бит 4 в #7FFD (BootROM/Basic)
|
||
* W0_WE: разрешить запись в окно #0000
|
||
* !W0_MAP: 0=маппинг через Page0, 1=стандартная страница 0
|
||
* W0_RAM: 0=ROM, 1=RAM в #0000
|
||
* LCK128: режим блокировки 128K-совместимости
|
||
* ──────────────────────────────────────────────────────────────────── */
|
||
#define TSCONF_PORT_MEMCONFIG TSCONF_PORT(0x21)
|
||
#define TSCONF_MEM_ROM128 0x01
|
||
#define TSCONF_MEM_W0_WE 0x02
|
||
#define TSCONF_MEM_W0_MAP_DIS 0x04
|
||
#define TSCONF_MEM_W0_RAM 0x08
|
||
#define TSCONF_MEM_LCK128_512K 0x00 /* 512K, биты 7:6 #7FFD=Page3[4:3] */
|
||
#define TSCONF_MEM_LCK128_128K 0x40 /* 128K, биты 7:6 #7FFD=00 */
|
||
#define TSCONF_MEM_LCK128_AUTO 0x80 /* Auto (!a[13]) */
|
||
#define TSCONF_MEM_LCK128_1M 0xC0 /* 1024K */
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* ПРЕРЫВАНИЯ — позиция FRAME-INT
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
|
||
/* ── HSINT (#22AF): горизонтальная позиция ─────────────────────────── */
|
||
/* HCNT[8:1] в диапазоне 0–223; >223 = выключить INT в этой строке */
|
||
#define TSCONF_PORT_HSINT TSCONF_PORT(0x22)
|
||
#define TSCONF_HSINT_OFF 0xFF
|
||
|
||
/* ── VSINTL (#23AF): вертикальная позиция [7:0] ────────────────────── */
|
||
/* VCNT[7:0]; строки 0–319; >319 = FRAME-INT выключен */
|
||
#define TSCONF_PORT_VSINTL TSCONF_PORT(0x23)
|
||
|
||
/* ── VSINTH (#24AF): вертикальная позиция [8] + автоинкремент ──────── */
|
||
/* Бит 0 = VCNT[8]; биты [7:4] = VINT_INC[3:0] */
|
||
/* VINT_INC: после каждого FRAME-INT → VCNT += VINT_INC (0 = нет) */
|
||
#define TSCONF_PORT_VSINTH TSCONF_PORT(0x24)
|
||
#define TSCONF_VSINTH_VCNT8 0x01
|
||
#define TSCONF_VSINTH_INC_MASK 0xF0
|
||
#define TSCONF_VSINTH_INC(n) (((n) & 0x0F) << 4)
|
||
|
||
/* ── INTMask (#2AAF): маска прерываний ─────────────────────────────── */
|
||
/* Сброс: 0x01 (только FRAME включён) */
|
||
#define TSCONF_PORT_INTMASK TSCONF_PORT(0x2A)
|
||
#define TSCONF_INT_FRAME 0x01
|
||
#define TSCONF_INT_LINE 0x02
|
||
#define TSCONF_INT_DMA 0x04
|
||
#define TSCONF_INT_WTP 0x08
|
||
|
||
/* Векторы IM2 (значение на шине данных при прерывании) */
|
||
#define TSCONF_IVEC_FRAME 0xFF
|
||
#define TSCONF_IVEC_LINE 0xFD
|
||
#define TSCONF_IVEC_DMA 0xFB
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* КЭШ — CacheConfig (#2BAF)
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_CACHECONFIG TSCONF_PORT(0x2B)
|
||
#define TSCONF_CACHE_EN_0000 0x01
|
||
#define TSCONF_CACHE_EN_4000 0x02
|
||
#define TSCONF_CACHE_EN_8000 0x04
|
||
#define TSCONF_CACHE_EN_C000 0x08
|
||
#define TSCONF_CACHE_ALL 0x0F
|
||
#define TSCONF_CACHE_NONE 0x00
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* FDD VIRTUAL DRIVE — FDDVirt (#29AF)
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_FDDVIRT TSCONF_PORT(0x29)
|
||
#define TSCONF_FDD_A 0x01
|
||
#define TSCONF_FDD_B 0x02
|
||
#define TSCONF_FDD_C 0x04
|
||
#define TSCONF_FDD_D 0x08
|
||
#define TSCONF_FDD_VG_OPEN 0x80
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* ТАЙЛОВЫЕ ПЛОСКОСТИ — смещения
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_T0XOFFSL TSCONF_PORT(0x40)
|
||
#define TSCONF_PORT_T0XOFFSH TSCONF_PORT(0x41)
|
||
#define TSCONF_PORT_T0YOFFSL TSCONF_PORT(0x42)
|
||
#define TSCONF_PORT_T0YOFFSH TSCONF_PORT(0x43)
|
||
#define TSCONF_PORT_T1XOFFSL TSCONF_PORT(0x44)
|
||
#define TSCONF_PORT_T1XOFFSH TSCONF_PORT(0x45)
|
||
#define TSCONF_PORT_T1YOFFSL TSCONF_PORT(0x46)
|
||
#define TSCONF_PORT_T1YOFFSH TSCONF_PORT(0x47)
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* HUS — Hurricane Sound Engine (#80AF–#87AF)
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_HUSCTRL TSCONF_PORT(0x80) /* W: управление */
|
||
#define TSCONF_PORT_HUSSAMPRATE TSCONF_PORT(0x81) /* W: SR[7:0] (1750k/(SR+1)) */
|
||
#define TSCONF_PORT_HUSTICKRATEL TSCONF_PORT(0x82) /* W: TR[7:0] */
|
||
#define TSCONF_PORT_HUSTICKRATEH TSCONF_PORT(0x83) /* W: TR[9:8] */
|
||
#define TSCONF_PORT_HUSRLD0 TSCONF_PORT(0x84) /* Reload ch 0–7 */
|
||
#define TSCONF_PORT_HUSRLD1 TSCONF_PORT(0x85) /* Reload ch 8–15 */
|
||
#define TSCONF_PORT_HUSRLD2 TSCONF_PORT(0x86)
|
||
#define TSCONF_PORT_HUSRLD3 TSCONF_PORT(0x87)
|
||
/* R: HUSStatus (#80AF) */
|
||
#define TSCONF_HUS_ACT 0x01
|
||
#define TSCONF_HUS_TICK 0x02 /* сбрасывается при чтении */
|
||
#define TSCONF_HUS_HALF 0x40 /* буфер наполовину пуст */
|
||
#define TSCONF_HUS_EMPTY 0x80
|
||
/* W: HUSControl */
|
||
#define TSCONF_HUS_PAUSE 0x02
|
||
#define TSCONF_HUS_RESET 0x80
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* OPL3 (YMF262) — порты на шине TSConfig
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_OPL3_ADDR0 0x00C4
|
||
#define TSCONF_PORT_OPL3_DATA0 0x00C5
|
||
#define TSCONF_PORT_OPL3_ADDR1 0x00C6
|
||
#define TSCONF_PORT_OPL3_DATA1 0x00C7
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* AY-3-8910 / YM2149 — стандартные порты ZX Spectrum 128
|
||
* ══════════════════════════════════════════════════════════════════════
|
||
* #FFFD — выбор регистра (W) / чтение данных (R)
|
||
* #BFFD — запись данных (W)
|
||
*
|
||
* TurboSound (два AY): запись в #FFFD значения #FF/#FE выбирает чип:
|
||
* #FF → чип 0 (первый AY); #FE → чип 1 (второй AY).
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_AY_ADDR 0xFFFD /* register select / read */
|
||
#define TSCONF_PORT_AY_DATA 0xBFFD /* data write */
|
||
#define TSCONF_AY_TS_CHIP0 0xFF /* TurboSound: select chip 0 */
|
||
#define TSCONF_AY_TS_CHIP1 0xFE /* TurboSound: select chip 1 */
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* SAA1099 — порты SAM Coupé / ZX-совместимые
|
||
* ══════════════════════════════════════════════════════════════════════
|
||
* #01FF — выбор регистра (address write)
|
||
* #00FF — запись данных (data write)
|
||
* Второй SAA1099 (если есть):
|
||
* #01FE — выбор регистра
|
||
* #00FE — запись данных
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define TSCONF_PORT_SAA_ADDR 0x01FF /* SAA1099 #1 address */
|
||
#define TSCONF_PORT_SAA_DATA 0x00FF /* SAA1099 #1 data */
|
||
#define TSCONF_PORT_SAA2_ADDR 0x01FE /* SAA1099 #2 address */
|
||
#define TSCONF_PORT_SAA2_DATA 0x00FE /* SAA1099 #2 data */
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* WC СИСТЕМНЫЕ ПЕРЕМЕННЫЕ — адреса в ROM-области ядра WC
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
#define WC_ADDR_PAGES 0x6000 /* [3 байта] страницы #0000,#4000,#8000 */
|
||
#define WC_ADDR_ABT 0x6004 /* флаг ESC */
|
||
#define WC_ADDR_ENT 0x6005 /* флаг ENTER */
|
||
#define WC_ADDR_TMN 0x6009 /* таймер (инкр. по INT), uint16 */
|
||
#define WC_ADDR_CNFV 0x600D /* версия конфигурации */
|
||
#define WC_ADDR_HEI 0x600E /* высота экрана (25/30/36 строк) */
|
||
|
||
#define WC_CNFV_PWM 0x00
|
||
#define WC_CNFV_3BIT 0x01
|
||
#define WC_CNFV_4BIT 0x02
|
||
#define WC_CNFV_5BIT 0x03
|
||
#define WC_CNFV_VDAC2 0x07
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* SFR — прямой доступ к портам из SDCC-C
|
||
* ══════════════════════════════════════════════════════════════════════
|
||
*
|
||
* __sfr __at 0xNN — 8-bit port: out (N), a / in a, (N)
|
||
* __sfr __banked __at 0xNNNN — 16-bit port: ld bc,#NNNN; out (c),a
|
||
*
|
||
* Не создают переменных/символов — чисто compile-time mapping.
|
||
* Присваивание sfr_xxx = val; генерирует inline OUT.
|
||
* Чтение val = sfr_xxx; генерирует inline IN.
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
|
||
/* --- Стандартный ZX Spectrum: 8-bit порт ----------------------------- */
|
||
__sfr __at 0xFE sfr_zx_fe; /* border / keyboard */
|
||
|
||
/* --- TSConfig регистры (addr = reg<<8 | 0xAF) ----------------------- */
|
||
__sfr __banked __at 0x00AF sfr_vconfig; /* VConfig */
|
||
__sfr __banked __at 0x01AF sfr_vpage; /* VPage */
|
||
__sfr __banked __at 0x02AF sfr_gxoffsl; /* GXOffsL */
|
||
__sfr __banked __at 0x03AF sfr_gxoffsh; /* GXOffsH */
|
||
__sfr __banked __at 0x04AF sfr_gyoffsl; /* GYOffsL */
|
||
__sfr __banked __at 0x05AF sfr_gyoffsh; /* GYOffsH */
|
||
__sfr __banked __at 0x06AF sfr_tsconfig; /* TSConfig */
|
||
__sfr __banked __at 0x07AF sfr_palsel; /* PalSel */
|
||
__sfr __banked __at 0x0FAF sfr_border; /* Border Color */
|
||
__sfr __banked __at 0x10AF sfr_page0; /* Page0 (#0000) */
|
||
__sfr __banked __at 0x11AF sfr_page1; /* Page1 (#4000) */
|
||
__sfr __banked __at 0x12AF sfr_page2; /* Page2 (#8000) */
|
||
__sfr __banked __at 0x13AF sfr_page3; /* Page3 (#C000) */
|
||
__sfr __banked __at 0x14AF sfr_fmaddr; /* FMAddr */
|
||
__sfr __banked __at 0x15AF sfr_tmpage; /* TMPage */
|
||
__sfr __banked __at 0x16AF sfr_t0gpage; /* T0GPage */
|
||
__sfr __banked __at 0x17AF sfr_t1gpage; /* T1GPage */
|
||
__sfr __banked __at 0x18AF sfr_sgpage; /* SGPage */
|
||
__sfr __banked __at 0x20AF sfr_sysconfig; /* SysConfig (CPU) */
|
||
__sfr __banked __at 0x21AF sfr_memconfig; /* MemConfig */
|
||
__sfr __banked __at 0x22AF sfr_hsint; /* HSINT */
|
||
__sfr __banked __at 0x23AF sfr_vsintl; /* VSINTL */
|
||
__sfr __banked __at 0x24AF sfr_vsinth; /* VSINTH */
|
||
__sfr __banked __at 0x2AAF sfr_intmask; /* INTMask */
|
||
__sfr __banked __at 0x2BAF sfr_cacheconfig; /* CacheConfig */
|
||
__sfr __banked __at 0x29AF sfr_fddvirt; /* FDDVirt */
|
||
|
||
/* --- DMA --- */
|
||
__sfr __banked __at 0x1AAF sfr_dmasaddrh; /* DMA Src Addr H */
|
||
__sfr __banked __at 0x1BAF sfr_dmasaddrx; /* DMA Src Addr X */
|
||
__sfr __banked __at 0x19AF sfr_dmasaddrl; /* DMA Src Addr L */
|
||
__sfr __banked __at 0x1CAF sfr_dmadaddrl; /* DMA Dst Addr L */
|
||
__sfr __banked __at 0x1DAF sfr_dmadaddrh; /* DMA Dst Addr H */
|
||
__sfr __banked __at 0x1EAF sfr_dmadaddrx; /* DMA Dst Addr X */
|
||
__sfr __banked __at 0x26AF sfr_dmalen; /* DMA Burst Length */
|
||
__sfr __banked __at 0x27AF sfr_dmactrl; /* DMA Ctrl / Status */
|
||
__sfr __banked __at 0x28AF sfr_dmanum; /* DMA Bursts Num L */
|
||
__sfr __banked __at 0x2CAF sfr_dmanumh; /* DMA Bursts Num H */
|
||
|
||
/* --- OPL3 (YMF262) --- */
|
||
__sfr __banked __at 0x00C4 sfr_opl3_addr0; /* Bank0 address */
|
||
__sfr __banked __at 0x00C5 sfr_opl3_data0; /* Bank0 data */
|
||
__sfr __banked __at 0x00C6 sfr_opl3_addr1; /* Bank1 address */
|
||
__sfr __banked __at 0x00C7 sfr_opl3_data1; /* Bank1 data */
|
||
|
||
/* --- AY-3-8910 / YM2149 --- */
|
||
__sfr __banked __at 0xFFFD sfr_ay_addr; /* reg select / read */
|
||
__sfr __banked __at 0xBFFD sfr_ay_data; /* data write */
|
||
|
||
/* --- SAA1099 --- */
|
||
__sfr __banked __at 0x01FF sfr_saa_addr; /* SAA1099 #1 address */
|
||
__sfr __banked __at 0x00FF sfr_saa_data; /* SAA1099 #1 data */
|
||
__sfr __banked __at 0x01FE sfr_saa2_addr; /* SAA1099 #2 address */
|
||
__sfr __banked __at 0x00FE sfr_saa2_data; /* SAA1099 #2 data */
|
||
|
||
/* ══════════════════════════════════════════════════════════════════════
|
||
* ФУНКЦИИ — обёртки
|
||
* ══════════════════════════════════════════════════════════════════════ */
|
||
|
||
/** Запись значения в произвольный TSConfig-порт (asm, для динамических адресов)
|
||
* @param port TSCONF_PORT(reg)
|
||
* @param val значение */
|
||
extern void tsconf_out(uint16_t port, uint8_t val);
|
||
|
||
/* ── Удобные макросы (через __sfr — inline, без call) ────────────────── */
|
||
|
||
/** Установить скорость CPU (TSCONF_CPU_3_5MHZ / 7MHZ / 14MHZ) */
|
||
#define tsconf_set_cpu(speed) \
|
||
(sfr_sysconfig = (uint8_t)((speed) & TSCONF_CPU_MASK))
|
||
|
||
/** Установить скорость CPU с управлением кэшем */
|
||
#define tsconf_set_cpu_cache(speed, cache_en) \
|
||
(sfr_sysconfig = (uint8_t)(((speed) & TSCONF_CPU_MASK) | ((cache_en) ? TSCONF_CACHE_EN : 0)))
|
||
|
||
/** Установить маску прерываний (OR нужных TSCONF_INT_*) */
|
||
#define tsconf_set_intmask(mask) \
|
||
(sfr_intmask = (uint8_t)(mask))
|
||
|
||
/** Настроить позицию FRAME-INT: line=0–319, hpos=0–223 */
|
||
#define tsconf_set_frame_int(line, hpos) do { \
|
||
sfr_vsinth = (uint8_t)(((line) >> 8) & 0x01); \
|
||
sfr_vsintl = (uint8_t)((line) & 0xFF); \
|
||
sfr_hsint = (uint8_t)(hpos); \
|
||
} while(0)
|
||
|
||
/** Выключить FRAME-INT полностью */
|
||
#define tsconf_disable_frame_int() \
|
||
(sfr_hsint = TSCONF_HSINT_OFF)
|
||
|
||
/** Настроить кэш по окнам: маска из TSCONF_CACHE_EN_* */
|
||
#define tsconf_set_cache(mask) \
|
||
(sfr_cacheconfig = (uint8_t)(mask))
|
||
|
||
/** Установить цвет бордюра (TSConfig-регистр) */
|
||
#define tsconf_set_border(color) \
|
||
(sfr_border = (uint8_t)(color))
|
||
|
||
/** Подключить видеостраницу (номер 0–63) на адрес #C000 */
|
||
#define tsconf_set_vpage(page) \
|
||
(sfr_vpage = (uint8_t)(page))
|
||
|
||
/** Установить видеорежим (OR из TSCONF_VM_*, TSCONF_RRES_*, TSCONF_VC_*) */
|
||
#define tsconf_set_vconfig(cfg) \
|
||
(sfr_vconfig = (uint8_t)(cfg))
|
||
|
||
/** Подключить RAM-страницу page на окно #C000 (Page3) */
|
||
#define tsconf_set_page3(page) \
|
||
(sfr_page3 = (uint8_t)(page))
|
||
|
||
/** Подключить RAM-страницу page на окно #8000 (Page2) */
|
||
#define tsconf_set_page2(page) \
|
||
(sfr_page2 = (uint8_t)(page))
|
||
|
||
#endif /* TSCONF_H */
|