/* * _cbl.h — внутренности CBL-модуля (НЕ публичный заголовок). * * Механика (форум Sprinter Team + официальная документация "5.3 * COVOX-Blaster" + docs/converted/accel_r.txt): * - порт управления 0x004E — 16-битный (только ld bc,#0x004E / * out (c),a): bit7 = CBL on, bit6 = stereo, bit5 = 16-бит, * bit4 = int enable, bits3..0 = частота; выключение — запись 0; * - буфер 256 Б аппаратно разбит на две половины по 128 Б; бит 7 * порта 0xFE отражает, какая половина ИГРАЕТ сейчас — флип этого * бита поднимает прерывание (вектор 0xFF), пора долить неактивную * половину; * - размер блока — 128 Б для 8-бит формата, 256 Б для 16-бит (не * зависит от моно/стерео) — см. _cbl_block; * - выдача блока — ДВА способа (cbl_push_otir.c/cbl_push_accel.c): * OTIR в порт 0x4F, либо акселератором в спец-страницу EMM 0xFD * (маппится в W3 на 0xC000); библиотека сама НИЧЕГО не пропихивает * — это делает fill()-callback приложения; * - насос вызывается из кадрового трамплина через хук _irq_cbl_hook * (см. _irq.h) — прямой ссылки irq→cbl нет, DCE сохраняется. * * Никакого собственного кольца НЕТ — второй буфер поверх аппаратного * был бы избыточен. _cbl_fill — callback приложения; _cbl_silence — * буфер тишины, malloc'ится в cbl_open() ТОЛЬКО при * CBL_UNDERRUN_SILENCE (иначе NULL). */ #ifndef _CBL_INTERNAL_H #define _CBL_INTERNAL_H #include #include #define _CBL_CTRL_PORT 0x004E #define _CBL_DATA_PORT 0x4F #define _CBL_ACCEL_PAGE 0xFD /* спец-страница EMM: запись на W3@0xC000 идёт в CBL */ extern uint16_t _cbl_block; /* размер блока: 128 или 256 (по формату) */ extern uint16_t _cbl_reqs; /* блоков-запросов обслужено */ extern uint16_t _cbl_undr; /* из них недолив (fill вернул 0/не задан) */ extern cbl_fill_fn _cbl_fill; /* callback приложения, может быть NULL */ extern uint8_t _cbl_underrun_mode; /* CBL_UNDERRUN_* */ extern uint8_t *_cbl_silence; /* буфер тишины или NULL */ /* Запись в 16-битный порт управления 0x004E. */ void _cbl_ctrl(uint8_t v); /* ISR-насосы: вызвать fill(), при недоливе — тишина по режиму (один * регистрируется в _irq_cbl_hook при cbl_open — по выбору CBL_PUMP_*). */ void _cbl_pump_otir(void); void _cbl_pump_accel(void); #endif