Прерывания
Содержание
- Обработчик прерываний по умолчанию
- Тайминги прерываний
- Аппаратный режим IM2
- Дополнительные сведения о таймингах из Discord от AA
Обработчик прерываний по умолчанию
Обработчик прерываний по умолчанию находится по адресу $0038 в ROM и автоматически вызывается Z80 в режиме прерываний Interrupt Mode 1.
Он:
- обновляет системную переменную - счетчик кадров;
- сканирует клавиатуру и обновляет системные переменные состояния клавиатуры.
Обработчик прерываний по умолчанию сохраняет все регистры и не имеет внешних зависимостей.
Вы можете заменить обработчик прерываний одним из следующих способов:
- Перевести Z80 в режим прерываний 2 (IM 2) и настроить адрес для пользовательского обработчика прерываний. Из-за ограничений спецификации прерываний Z80, это требует размещения обработчика прерываний по адресу, где старший и младший байты совпадают.
- Использовать Next Memory Management для выгрузки ROM по адресу $0038 и заменить его страницей RAM с вашей собственной подпрограммой со смещением $38.
Тайминги прерываний
Стандартный ULA Spectrum генерирует прерывание каждый видеокадр. Это очень часто используется в играх для синхронизации графики с обновлениями экрана.
Вы можете настроить тайминги видео прерываний, используя Регистр управления прерыванием видеолинии ($22). Это позволит вам добавить дополнительное прерывание, которое происходит по определенному адресу строки, или отключить стандартное прерывание ULA.
Использование этого регистра для “перемещения” стандартного прерывания сразу после последней строки видимого экрана может увеличить время, доступное для обработки между кадрами.
Аппаратный режим IM2
В отличие от обычного режима IM2, который, с точки зрения программиста, соответствует поведению оригинального ZX Spectrum, в ядре версии 3.02.00 и выше существует новый “Аппаратный режим IM2”. Он позволяет настраивать разные обработчики прерываний для разных источников прерываний.
Аппаратный режим IM2 включается битом 0 регистра Next 0xC0 (Interrupt Control ($C0)) и имеет полный набор приоритезированных и связанных прерываний, каждое со своими четко определенными векторами. В этом режиме, когда происходит IM2, младшие 8 бит адреса устанавливаются, как описано в справочной документации регистра C0 Next: https://gitlab.com/SpectrumNext/ZX_Spectrum_Next_FPGA/-/blob/master/cores/zxnext/nextreg.txt?ref_type=heads
Запросы прерываний кэшируются и удерживаются, пока обслуживается прерывание более высокого приоритета, затем запускаются (возможно, с опозданием), как только прерывание более высокого приоритета завершается. Все возвраты в этом режиме должны выполняться с помощью reti, чтобы оборудование могло отслеживать приоритеты.
В стандартном режиме и на обычных Spectrum, если прерывание пропущено (линия /INT освобождается до принятия прерывания), то прерывание теряется навсегда.
Дополнительные сведения о таймингах из Discord от AA
Медный сопроцессор считает в соответствии с пикселем, который в данный момент генерируется, где (0,0) соответствует позиции (0,0) экрана ULA размером 256x192. Вы можете настроить положение вертикального 0 для медного сопроцессора через nextreg, но не горизонтальное положение (пока?). Прерывание по строке и положение растровой строки также используют вертикальную координату медного сопроцессора.
ULA фактически считывает данные пикселей и атрибутов за 12 пикселей до их отображения. Итак, если регистры медного сопроцессора x=0, что указывает на то, что генерируется пиксель 0, то ULA извлекла эти данные пикселя/атрибута в течение предыдущих 12 циклов.
Прерывание по строке для line=y происходит в line=y-1, x=256, насколько я помню. То есть, прерывание происходит сразу после того, как область в 256 пикселей была нарисована в ПРЕДЫДУЩЕЙ строке. Это сделано для того, чтобы дать максимальное время для выполнения действий ДО того, как будет нарисована указанная строка.
Прерывание VBI от ULA происходит там же, где и на Spectrum, что я сразу не помню. Это во время вертикального гашения, вероятно, при x=0 или 1. Видеокадр 128K немного позже при x=1, потому что машины 128K имеют RC-конденсатор на печатной плате на линии /int от ULA.
Если вам нужна большая точность по таймингам прерываний, вы можете заставить медный сопроцессор генерировать прерывания через nextreg.