Ресурсы УКНЦ/Глава 5

Материал из Emuverse

Глава 5. Использование сетевого таймера. Курсор, кулон и прочее.


Жалоба на жизнь

Писать книгу — занятие чертовски сложное. Писать книгу об УКНЦ — вдвойне. И вот почему.

Разобраться в работе запутанных программ и в их хитросплетениях — это во-первых.

Объяснить всё найденное, да так, чтобы в написанном смогли разобраться не только авторы, но и некоторые читатели, причем без потери душевного здоровья обеими сторонами — это во-вторых. Всё вместе временами разрастается в глобальную проблему «А нужно ли?!». И лишь врожденная иррациональность воли двигает авторов к продолжению работы. А посему продолжаем.

В этой главе мы разделаемся с сетевым таймером ПП, точнее, с программой, если обслуживающей.

Попутно мы разберем механизм работы, а так же стандартный механизм управления курсором.

Затем будут даны обобщающие рекомендации по многоэкранному выводу.

И напоследок обобщим всю 1 часть, которая посвящена экрану УК-НЦ.


§ 13. Управление курсором

Всяк имеющий дело с ЭВМ понимает что такое курсор (хотя бы интуитивно). Попробуем дать ему определение:

Курсор — это объект на экране, с должной периодичностью меняющий своё видимое состояние и показывающий место, куда следует отображать всяческие символы, будь то цифры, буквы или ещё что.

В системе стандартный курсор представляющий собой мигающий прямоугольничек размером 8x9 точек, цвет которого можно менять. Также меняется местоположение курсора на экране. Обычно он занимает позицию текущего знакоместа.

Курсор отображается аппаратным способом, а его местоположением и состоянием (включен/выключен) управляет программа обработки прерываний от сетевого таймера.

Несколько слов о сетевом таймере.

Сетевой таймер — это устройство с простой функцией: вырабатывать 50 раз в секунду прерывание с А. В.П. 100(8). Прерывание вырабатывается, если оно не замаскировано, и если таймер выключен.

И в ЦП, и ПП можно использовать это устройство. Его включением/выключением заведует регистр в ПП с адресом 177054, притом управлять сетевым таймером можно раздельно для каждого процессора.

Частота 50 Гц выбрана не случайно. Это — частота кадровой развертки, то есть сам сигнал кадровой развертки связан с выработкой прерываний.

Сетевой таймер весьма удобно использовать в программах, активно использующих мультипликацию. Действительно, менять кадры с частотой, большей частоты кадровой развертки, не имеет смысла. И если связать рисование кадров с прерыванием частотой 50Гц, можно получить качественные, плавные мультики на экране.

Системная программа обработки прерываний управляет курсором, рулоном, автоповтором нажатых клавиш, а так же позволяет вызывать люб подпрограммы с частотой не более 50 Гц.

Позиционирование курсора

В 1-й главе было сказано, что цвет и позиция курсора определяет 1-е слово регистра управления отображением. Так оно и есть.

15 14 8 7 5 4 3 0

     позиция   позиция   тип  цвет
     октета     гр. кур.

Разряды 0...3 управляют цветом, разряд 4 - тип курсора (символьный - графический), разряды 5...7 - позиция гр. курсора в октете, разряды 8...14 - позиция октета или символьного курсора на экране.

По горизонтали

В системе использован символьный курсор. Его горизонтальным положением заведует старший байт УО1. Есть такой нюанс: максимальное положение на экране курсора 79, т.е. 117(8) (крайнее правое положение при режиме 80 символов). Но УО1 позволяет задавать положение вплоть до 177(8). При этом курсор пропадает из поля видимости. Это используется в системе для периодического "гашения" курсора.

Вместо того, чтобы менять цвет, курсор отсылается в несуществующую позицию (177) и его не видно. Адрес УО1 (ст. байт) содержит ячейка в ЭК со смещением 62.

Этот же адрес для текущего экрана содержится в переменной с адресом 23160. Т.е. чтобы изменить позицию курсора, надо выполнить действия с операндом @(23160). Позиция включенного курсора содержится в ячейке 23156.

По вертикали

Теперь рассмотрим позиционирование курсора по вертикали. Уже говорилось, что наличие или отсутствие курсора в данной видео-строке определяется в таблице строк. Нулевой разряд последнего слова любого элемента позволяет переключать состояние курсора.

Формирование курсора высотой в 9 байт делается так.

В экранной карте переменная 60 содержит адрес той строки, где начинается "курсорное знакоместо". Это адрес адрес в таблице строк. Если учесть что посреди экрана все элементы двухсловные, то этот адрес будет указывать на последнее слово следующего элемента. Нулевой бить его устанавливается в 1. Тот же адрес плюс 52(8) будет указывать на предпоследний элемент этого знакоместа, на его последнее слово. И здесь устанавливается нулевой бит.

Таким образом курсор оказывается заключен между верхним и нижним октетами знакоместа, т.е. состоит из 9 октетов. Рис 13.0.

13.2. Механизм управления курсором

В управлении курсором принимают участие:

- диспетчер - программа экранного вывода - сетевой таймер

Начнем с конца с сетевого таймера.

На схеме 13.0 показана блок-схема программы обработки прерываний.

Эта программа занимается курсором, если не надо крутить рулон ((23170)=0).

В зависимости от содержимого ячейки (7134) возможны 3 варианта действий

1) (7134)=0:

Позицией курсора становится текущее знакоместо. Для этого:

в R0 пишется разность между адресом ВОЗУ начала текущей строки и текущим адресом ВОЗУ, т.е. текущая позиция по X.

Это значение в зависимости от формата увеличивается:

	80 мест - в 1 раз (не меняется)
	40 мест - в 2 раза
	20 мест - в 4 раза
	10 мест - в 8 раз. Множитель содержится в ЭК. Его смещение - 66.

Связано это с тем, что позиция курсора на экране не меняется параллельно изменению формата, меняется лишь размер самого курсора (увеличиваются точки). Для того, чтобы курсор поспевал за текущим знакоместом и приходится домножать позицию.

Получившееся значение переписывается в (23156). Затем убирается курсор со старого места (из знакоместа, которое определяет (RS+60)), и и рисуется вновь на текущей символьной строке (её начало определяет (RS+32)).

Наконец ячейке (7134) присваивается значение 4.

2) (7134) = 2.

No Operation. Курсор вообще не трогается.

3) (7134) = 4.

В этом случае идёт работа с "миганием". В результате работы весьма хитрого алгоритма курсор мигает со временем полного цикла 1,6 сек. Из них 0,96 сек. курсор включён, а 0,64 сек. - выключен.

При включении курсора в УО1 пишется позиция из (23156), а при выключении - значение 177(8).

Программа экранного вывода и Диспетчер также прикладывают руку к управлению курсором.

В самом начале выполнения экранного вывода программа устанавливает ячейку 7066, которая, как известно, входит в состав таблицы запросов.

По выходе из программы управления возвращается Диспетчеру, и тот, найдя (7066), отличную от нуля, отправляется на адрес 176056. Там выполняется весьма нехитрые действия (схема 13.1): в зависимости от (23164) либо разрешается перерисовка курсора ((7134)=0), либо нет.

Переменная (23164) загружается при прокрутке рулона из ЭК, ячейки со смещением 72.

Таким образом, (R5+72) отвечает за отслеживание курсором текущего знакоместа в каждом из экранов, а (23164) - в текущем экране.

Их значения:

0 - отслеживания нет.
2 - отслеживание есть (курсор располагается в текущем знакоместе).

Самое время обобщить и упорядочить то, что мы знаем о курсоре:

Резюме к § 13

- Курсор - "Экранный призрак". Он рисуется аппаратно "поверх" изображения на экране. То есть при рисовании курсора, не затрагивается и не тревожится видеоинформация в ВОЗУ.

- Информация о курсоре содержится в таблице строк.

- Обычно курсор представляет собой мигающий прямоугольничек 8x9 точек. Однако аппаратура УК позволяет разнообразить вид курсора.

- Вид курсора (и графическая позиция) указывают в регистре управления отображением, в его 1-м слове (УО1). Этот вид действует во всех строках, где действует данный регистр УО.

- Курсор может быть графическим или символьным. Графический - это лишь одна точка, зажженная в данном октете. Символьный - зажжен весь октет. В данной строке курсор может находиться лишь в одном единственном октете в данный момент времени.

- Наличие курсора в данной строке определяет нулевой разряд последнего слова элемента ТС. Установкой либо сбрасыванием этого разряда в двух строках можно поставить курсор в определенную вертикальную позицию на экране - заключенного между этими строками.

- Чтобы курсор отслеживал текущее знакоместо (занимал его позицию), нужно переменной (23164) присвоить значение 2. Значение 0 приведёт к тому, что курсор будет мигать лишь в одном месте экрана и будет игнорировать текущее знакоместо (которое будет, конечно, меняться).

- Вызов диспетчером программы экранного вывода (вывод символа или вызов спецфункции) каждый раз ведет к тому, что в ней устанавливается запрос на отслеживание курсором (7066). Этот запрос затем обрабатывается Диспетчером так:

если (23164)=2, то (7134) обнуляется.

- Ячейка (7134) обнуляется программой обработки прерываний от сетевого таймера ПП.

Если она равна 0, курсор курсор ставится в текущей знакоместо, а (7134) присваивается значение 4. Если она равна 2, ничего с курсором не происходит. Если она равна 4 - работает механизм мигания курсора.

- Текущую горизонтальную позицию курсора содержит ячейка (23156), она переписывается в УО1, старший байт, адрес которого (нечетный) хранится в ячейке (23160).

- Для "гашения" курсора используют позиции, при которых курсор пропадает с экрана (>79)/

- В экранных картах 6 ячеек связаны с курсором, вот они:

Смещение Значение

  60           Адрес элемента в таблице строк,
  				с которого берет начало курсорное знакоместо.
  66			"Кратность позиции". Для форматов экрана меньше 80 символов
  				приходится домножать позицию курсора в N раз, где N = 80/формат.
  				Здесь это N и сидит.
  70			Цвет курсора. Позволяет также задавать и графический курсор и его позицию в октете.
  				Загружается в УО1.
  72			Отслеживание курсором текущего знакоместа
  				0 - нет
  				2 - да. Загружается в (23164)
  62			Адрес старшего байта УО1.
  				( в него пишется позиция символьного курсора)
  64			Адрес младшего байта УО1.
  				(в него пишется цвет курсора, и, при желании, позиция графического курсора).


§ 14. Рулон

Эта функция ввода-вывода также возложена на плечи таймерной программы.

Её основное применение - Scrolling экрана. То есть когда текущее знакоместо в последней строке, и поступила команда двигаться ещё ниже, весь экран сдвигается вверх. Либо наоборот: курсор, подойдя к верхнему краю экрана, желает двигаться выше, то тогда экран ползёт вниз на одну символьную строку.

При этом строки, выплывающие сверху или снизу предварительно очищаются.

Есть также функции прокрутки экрана:

экран циклически сдвигается вверх или вниз, при этом видеоинформация во вновь появляющихся строках не теряется.

14.0. Основные принципы работы рулона

Рулон работает только в рабочем экране.

Рабочий экран состоит из 26 символьных строк. 24 их них отображены на экране в "окне" между верхней и нижней инфо-строками. 2 не умещаются.

Различия между этими строками нет очевидно никакого, и "невидимыми" могу стать любые строки, уплыв с экрана через верхний или нижний край.

Чтобы уяснить себе работу рулона, можно представить таблицу строка как цепь, состоящую из отдельных звеньев (элементов). Каждое звено связано со следующим (каждый элемент указывает на следующий).

Очередность звеньев в такой цепи можно менять. Это и делается с таблицей строк.

Чтобы, к примеру, сместить экран вверх на одну видеостроку, мы "цепляем" его за следующий элемент. Поясним.

Адрес элемента, представляющего верхнюю строку "окна", содержится в ячейке (2476). Номинальное её содержимое - 2500, т.е. адрес начала рабочего экрана в ТС. Теперь пишем в (2476) адрес 2504. В результате, наша верхняя строка пропадёт, на её место встанет следующая, и весь экран поднимется наверх (исключая верхнюю инфо-строку).

Чтобы оставить нижнюю инфо-строку на прежнем месте (она ведь не обязана участвовать в авантюрах с рабочим экраном), нужно всунуть внизу рабочего экрана строку (т.е. ещё один элемент). Поскольку элементы нижней инфо-строки начинаются с ячейки 6742, этот адрес мы пишем в последнее слово прицепляемого элемента. Адрес же самого элемента надо записать во второе слово предыдущего (вместо числа 6742). Вот теперь готово.

Откуда мы берём новый элемент и куда денем убранный?

Все элементы рабочего экрана располагаются в ТС один за другим. Начальный адрес - 2500, конечный - 4666. Сами элементы мы не перемещаем, а лишь меняем связи между мини, т.е. меняем содержимое вторых слов некоторых элементов.

Иными словами это можно выразить так: не рабочий экран прокручивается внутри окна, а окно ездит по рабочему экрану (Рис 14.0).

Итак, указанным способом можно прокрутит экран на произвольное число видео-строк.

Если нижний край окна подойдёт к последнему элементу рабочего экрана (при движении экрана вверх), ничто не мешает в ячейку (4666) - в последнее слово последнего элемента - записать число 2500 (адрес первого элемента).

Если же верхний край окна подойдёт к первому элементу (при движении экрана вниз), в таком случае верхним элементом станет последний элемент.

Таким образом, первый и последний элементы сцепляются наподобие кольца. Тогда рабочий экран можно представить как бесконечную ленту склеенную из участков по 26 символьных строк, вдоль которой ездит окно (рис. 14.0), обрамленное информационными строками.

Конечно, информация в этих участках повторяется.

14.1 Реализация рулона

Рулон может находиться в двух состояниях:

 - плавный
 - дискретный

В первом случае за один тик происходит смещение на одну видео-строку, пока (23170) не станет равно 0 (т.е. на 50 строк в секунду).

Во втором - сразу же проиcходит сдвиг на требуемое количество видео-строк за одно прерывание от сетевого таймера, и (23170) обнуляется.

Теперь разберем схему программы обработки прерывания от сетевого таймера.

Взглянем на схему 13.0. Эта схема начинается с того, что анализируется ячейка (23170). Эта ячейка выполняет роль счетчика рулона и содержит требуемое смещение (в пикселях), которое имеет знак. Так, например, чтобы прокрутить вниз экран на одну символьную строку, надо записать в (23170) число 177765(8) (-13(8) в дополнительном коде).

Итак, положительные числа соответствуют движению вверх, отрицательные - вниз.

За плавность рулона отвечает ячейка (7136):

 0 - плавный рулон
 2 - дискретный

Выключается рулон ячейкой в ЭК со смещением 74:

 0 - выключен
 2 - включен.
Выключение рулона означает лишь что в программе экранного вывода рулон не работает.
Работу программы (в различных вариантах вверх-вниз, плавный-дискретный) проследить теперь нетрудно, ибо её основные причины мы уже изложили.
Заметим лишь, что в них фигурируют числа 2040 и 2170.
  2040 - это размер отрезка таблицы строк, представляющего 24 символьные строки ("окно").
  2170 - это размер участка таблицы строк, представляющего весь рабочий рулон - 26 символьных строк.

14.2 О связи рулона с курсором

Немножко обговорим тот факт, что рулон также причастен к управлению курсором.

Рулон может вызываться двумя способами:

1) Из спецфункций СФ-22 и СФ-26 (Scroll up & down)

Эти спецфункции сами по себе никак курсором не управляют, они лишь меняют содержимое ячейки (23170) на 13(8) (в ту или иную строну).

2) Непосредственно из программы экранного вывода (движение курсора за пределы экрана вверх или вниз).

В этом случае перед тем, как записать в (23170) нужное число делается следующее:

- выключается отслеживание курсором текущего знакоместа: (23164)=0.
- выключается мигание курсора: (7154)=2.
- курсор гасится: @(23160)(8)=177.

Далее включение курсора осуществляется либо при вызове программы экранного вывода, либо в самой рулонной программе (сетевой таймер):

когда обнуляется счётчик рулона (конец прокрутки), ячейка отслеживания загружается из ЭК рабочего экрана (23164)=(22750), и устанавливается запрос Диспетчеру на включение курсора - (7066)+1.

§ 15. Периодический вызов программы и управление звуком от СТ

Вы можете использовать программу сетевого таймера (СТ) с весьма полезной целью: вызов Ваших процедур с частотой 50Гц, а так же 50/2, 50/3, 50/4 Гц и так далее.

При этом не нужно перехватывать прерывания от таймера.

Достаточно загрузить 2 ячейки:

(7130) - программный счетчик сетевого таймера (7132) - ячейка адреса вызываемой подпрограммы.

Работа программы обработки прерываний СТ с этими ячейками сводится к следующему:

Если счетчик (7130) отличен от 0, из него вычитается 1. Затем он опять проверяется на 0, и если условие (7130)=0 выполняется, вызывается подпрограмма, адрес которой в ячейке (7132).

Ваша процедура может делать всё что угодно. Но желательно, чтобы её время работы укладывалось в 1/50 сек., иначе будут пропущены следующие тики - прерывания от СТ.

И ещё. В теле Вашей процедуры необходимо каждый раз обновлять значение ячейки (7130) - счетчика, ведь к каждому вызову вашей процедуры он равен 0.

Значение 1 ведет к выполнению процедуры с частотой 50 Гц, 2 - 25Гц и т.д. т.е. счетчик ещё и выполняет роль делителя частоты вызова процедуры.

А теперь - немного о звуке.

Сразу после анализа счетчика (7130) (и после вызова процедуры с адресом в (7132)), делается следующее:

- декрементируется ячейка (7046).
- в случае, если она равна 0, выключается звуковой канал (сбрасываются 7-12 разряды системного регистра):
  BIC #17600,@#177716

Таким образом, ячейка (7046) служит счетчиком, уменьшающимся на единицу 50 раз в секунду.

Это используется, к примеру, в СФ-7, выполняющей звуковой сигнал (BEEP).

Выключается звук : (177716)!600
Загружается счетчик : (7046)=20.

Спустя 16 тиков (0,32 секунды) звук выключается.

Резюме к §§ 14 и 15

- Рулон занимается "перемоткой" рабочего экрана вверх-вниз.

- Рабочий экран составляет 26 символьные строки. Все они участвуют в циклическом сдвиге, хотя лишь 24 из них постоянно видны.

- При прокрутке экрана с помощью СФ-22 (вверх) или СФ-26 (вниз) видеоинформация экрана не меняется.

- При сдвиге вверх или вниз с помощью программы экранного вывода строки, выплывающие из нижнего либо из верхнего края экрана соответственно, очищаются.

- Работа рулона заключается в манипуляциях над таблицей строк, при этом меняется очередность вывода на экран видеострок в окне.

- Рулон можно выключить (для программы экранного вывода). за использование рулона непосредственно из неё отвечает последняя ячейка ЭК (смещение 74):

 0 - выключен
 2 - включен

на работу СФ-22 и СФ-26 это не распространяется.

- Рулон может быть плавным либо дискретным.

В первом случае экран сместится на 50 видеострок в секунду (плавно). Во втором - за 1 раз достигается нужная позиция.

Ячейка (7136) отвечает за плавность:

 0 - плавный рулон
 2 - дискретный рулон

- Количество видеострок, на которое следует сдвинуть экран задается в ячейке (23170). Положительные числа - крутим вверх. Отрицательные - вниз.

- Для выполнения какой-либо процедуры с частотой 50/n Гц делают следующее:

  в ячейку (7132) пишут адрес процедуры,
  в ячейку (7130) - n (коэффициент частоты)

При каждом вызове процедуры нужно вновь записывать число n в (7130)/

- Ячейка (7046) при каждом прерывании от сетевого таймера уменьшается на 1, в случае, если оно равно 0, выключается звуковой канал (обнуляются разряды 7-12 системного регистра).