Files
Sprinter-SDCC/libc/irq/irq_ctc_install.c
T
snark13 8a952b99eb irq: Phase 2a — CTC-таймер на отдельном векторе 0x06 (Z84C015)
- irq_ctc_install(handler, div2, div3) / irq_ctc_remove: канал 2 CTC
  делит видеотакт 875 кГц (1 тик = 1 знакоместо), канал 3 считает от
  него и прерывает; f = 875000/(div2*div3), div 0 = 256. Пресет
  IRQ_CTC_VSYNC_DIV2/3 = 112*160 — точное начало кадра ~48.8 Гц БЕЗ
  примеси клавиатуры (вектор 0x06 отделён от общего 0xFF)
- CTC-трамплин: полный сейв -> handler -> EI/RETI; RETI обязателен
  (daisy chain Z84C015 снимает IUS только по опкоду RETI); к DSS не
  чейнится — личное прерывание
- общая IM2-таблица под счётчиком ссылок (_irq_table.c): кадровый и
  CTC-хендлеры независимы, последний unref возвращает I/IM 1;
  atexit-уборка глушит CTC обязательно (иначе кГц-прерывания душат
  шелл после выхода)
- порты/слова по docs/samples: CH0=0x10/CH2=0x12/CH3=0x13,
  0x57/0xD7/вектор в CH0, стоп 0x03
- irqtest: CTC-vsync параллельно с кадровым + произвольная частота;
  MAME: frame 48 Гц, ctc(vsync) 49 Гц (parallel frame жив),
  ctc(50x50) 350 Гц точно по формуле, remove/выход чистые

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 09:15:04 +03:00

61 lines
2.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* irq_ctc_install — периодический user-таймер на CTC Z84C015
* (каналы 2+3 в связке, вектор 0x06 — ОТДЕЛЬНЫЙ от кадрового 0xFF).
*
* Канал 2 тактируется видеотактом 875 кГц (1 тик = 1 знакоместо) и
* работает делителем; канал 3 считает от канала 2 и генерирует
* прерывание. Частота = 875000 / (div2 * div3), div 0 = 256.
* Пресет кадра: 112 * 160 (2 пиксельные линии * 160 = 320 линий) —
* точное начало кадра ~48.8 Гц без примеси клавиатуры.
*
* Программирование (docs/samples/sprinterIntLib.asm, SIO_CTC_KEY.asm;
* значения control-слов «надо читать доку по z84c15»):
* 0x57 -> CH2, div2 — счётчик, без прерывания
* 0xD7 -> CH3, div3 — счётчик, прерывание разрешено
* 0x00 -> CH0 — базовый вектор блока CTC = 0 (ch3 -> 0x06)
*/
#include <errno.h>
#include "_irq.h"
static uint8_t ctc_div2;
static uint8_t ctc_div3;
static void ctc_program(void) __naked
{
__asm
ld a, #0x57 ; CH2: counter, int off, TC следом
out (#_IRQ_CTC_CH2), a
ld a, (_ctc_div2)
out (#_IRQ_CTC_CH2), a
ld a, #0xD7 ; CH3: counter, int on, TC следом
out (#_IRQ_CTC_CH3), a
ld a, (_ctc_div3)
out (#_IRQ_CTC_CH3), a
xor a, a ; базовый вектор CTC = 0
out (#_IRQ_CTC_CH0), a
ret
__endasm;
}
int irq_ctc_install(isr_t handler, uint8_t div2, uint8_t div3)
{
if (!handler) { errno = EINVAL; return -1; }
if (_irq_ctc_user) { errno = EBUSY; return -1; }
if (_irq_table_ref() != 0) return -1;
uint16_t tramp = (uint16_t)&_irq_ctc_tramp;
uint8_t *table = _irq_table();
IRQ_DISABLE();
_irq_ctc_user = handler;
/* Вектор 0x06 — обычная (не same-byte) запись в таблицу. */
table[0x06] = (uint8_t)(tramp & 0xFF);
table[0x07] = (uint8_t)(tramp >> 8);
ctc_div2 = div2;
ctc_div3 = div3;
ctc_program();
IRQ_ENABLE();
return 0;
}