** Сайт посвящённый ПЭВМ АГАТ **

Структура контроллера

Из чего состоит дисковод - неплохо, и, даже, по русски, описано в оригинальной болгарской документации, так что тут ничего нового я всё равно не напишу.

Гораздо интереснее сам контроллер. Его можно условно разделить на следующие блоки:

Шинный интерфейс

Пока без комментариев.

ПЗУ начального загрузчика

Без комментариев

Защелки состояния

Восемь отдельных триггеров. Любая операция процессора с портами ¤C0x0..¤C0xF приводит к установке нового состояния защелки. Забудьте о том, что написано в инструкциях к Агату, по крайней мере до следующего раздела. Защёлки адресуются тремя битами адресной шины A3, A2, A1, а значение, которое они запоминают, берется с шины A0. Т.е. каждый чётный адрес выключает какую-то защелку, каждый нечётный - включает. Прочитать состояние защёлок центральный процессор не может. Защёлки влияют на следующие функции:

Секвенсор

Это микро-микро-микроэвм (или пикоэвм - кому как нравится). Архитектурно: содержит ПЗУ с четырьми процедурами и два регистра, один из которых выполняет роль АЛУ и аккумулятора, а второй - указателя команд. Каждая процедура имеет два бита-аргумента и состоит из 16 команд. Любая команда выполняется за один такт, частота тактирования - 2 МГц. Система команд состоит из 6 операций.

Аккумулятор секвенсора доступен ЦПУ на чтение и запись. Почти в любой момент. Программа ЦПУ может попытаться обратиться к нему, прочитав любой регистр ¤C0x0..¤C0xF. И записать в него новое значение, выполнив операцию записи в любой регистр ¤C0x0..¤C0xF. Т.е. в доступе к аккумулятору не используется какого либо декодера адреса.

Чтение в агатовском контроллере возможно почти в любой момент, запись - только когда программа секвенсора готова к приёму данных. Этот вопрос позднее будет рассмотрен более подробно.

Эпловский контроллер отличается тем, что у него для чтения доступны только чётные адреса, запись же возможна только по нечётным адресам. Попытка записи по чётному адресу приведёт к аппаратному конфликту на шине: т.е. управлять шиной данных попытается и ЦПУ и контроллер. Системный сигнал R/!W он просто игнорирует.

А как же защёлки ? ;))) А вот так вот. Именно в этом и суть. Они будут переключатся. И влиять на работу секвенсора, т.е. на содержимое его аккумулятора. Сопоставив скорость работы ЦПУ - каждая команда 2-4 такта на частоте 1 МГц, т.е. около 2-4 мкс на команду и скорость работы секвенсора - команда 1 такт на частоте 2 МГц, т.е. 0.5 мкс на команду, увидим, что порядок срабатывания защелок и вообще расписание работы ЦПУ здесь становится очень важно.

Из схемы шинного интерфейса следует, что защёлки срабатывают в первой полуволне тактовой частоты ЦПУ (на подъём уровня ф1, когда ЦПУ уже установил значения на шине адреса), а буферные усилители включаются во второй полуволне (на спад ф1, здесь ЦПУ выполняет чтение шины данных). Также именно спад ф1 является тактовым сигналом секвенсора. Отсюда первый важный, но неочевдный вывод: защелки меняют состояние до того, как очередную команду выполнит секвенсор. Но секвенсор может выполнить несколько команд до того, как ЦПУ захватит данные из его аккумулятора.

Процедуры секвенсора

В качестве входных данных секвенсор получает четрые бита. Два бита от защёлок 6 и 7, один бит - читаемые данные, один бит - старший разряд аккумулятора.

Сразу разберёмся с читаемыми данными: они проходят цифровую дифференцирующую (я правильно слово выбрал?) цепочку. Её задача: выделить спадающий фронт сигнала, который поступает от дисковода. Т.е. эта цепочка всегда возвращает последовательность вида 111101111 (выход цепочки - инвертирующий), независимо от того, какая реальная длительность "1" получена от дисковода (важно лишь, чтобы она была не короче 500 нс или хотя бы имелась в момент прохождения сигнала синхронизации секвенсора).

Весь управляющий код секвенсора можно условно разделить на четыре процедуры.

Процедура чтения бита "Защита записи"

Эта процедура самая простая, поэтому начнём с неё. Она полностью состоит из команд сдвига аккумулятора вправо, при этом старший разряд заполняется значением сигнала "защита записи", поступающего на контроллер от дисковода.

Процедура адресуется комбинацией "C/D = 1" & "Write = 0". Вспоминаем мануал:
lda ¤C0xD
lda ¤C0xE
bmi WrPr

На самом деле, в свете вышеизложенного, становится понятно, что многие другие комбинации тоже могут оказаться работающими: lda ¤C0xE
lda ¤C0xD
bmi WrPr

Какая разница, в каком порядке переключать защёлки, если важно только их конечное состояние ? А вот на эпле этот фокус уже может не пройти: lda ¤C0xD - чтение нечётного адреса - даст мусор.

Более экзотичная комбинация:
sta ¤C0xD
bit ¤C0xE
lda ¤C0x2
bmi WrPr

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

Процедура захвата данных с шины ЦПУ

Процедура вроде бы не сложная, но в ней имеется одна тонкость, которая неопытному программисту может испортить нервы. А опытный программист, однажды столкнувшись с нею, вообще с досады волосы себе выдерет :) и с воплями "кто ж так строит ?!" кинется из окна.

Эта процедура активируется комбинацией защёлок "C/D = 1" & "Write = 1".

Т.е. после того, как вы проверили состояние защиты записи, просто выполняем запись байта по адресу
sta ¤C0xF
Это приводит к переключению защёлки Write. Секвенсор начинает выполнять новую процедуру и на третьем от начала такте захватывает в аккумулятор значение, выставленное на шину данных.

А в чём хитрость ? А в том, что ЦПУ выставляет значение на шину данных в третьем такте только при исполнении команды "sta ¤C08F, x" (при условии непересечения границы страниц в результирующем адресе!). Например, команда "sta ¤C0xF" выполняется чуть быстрее, и к третьему такту на шине данных уже будут совсем другие цифры.

Процедура сдвига данных из аккумулятора на линию записи дисковода

Активируется комбинацией "C/D = 0" & "Write = 1".

Как выглядит полная процедура записи байта ?
sta ¤C0xF, x
ora ¤C0xC, x

Официальный мануал говорит нам о том, что команда "ora ¤C0xC, x" нужна, чтобы начать запись данных из регистра, где байт, якобы, сохраняется и может быть затем записан повторно. Негде ему там сохраняться - аккумулятор у секвенсора всего один ! И именно он используется для сдвига бит. Но ora действительно нужна для переключения процедуры секвенсора с захвата на сдвиг. Если её не выполнить - секвенсор, через 8 своих тактов после захвата данных от sta, вновь начнёт слушать шину данных и ему не важно - пригласили его туда или нет :).

Сдвиг бита происходит на каждый восьмой такт секвенсора, т.е. каждые 4 мкс.

Что важно: во время последовательной записи нескольких байт драйвер должен заботится о двух вещах: 1) каждые 32 мкс прикармливать секвенсор новым байтом, 2) после каждой прикормки, не позднее 4 мкс, переключить секвенсор в режим сдвига. Как именно он это будет делать - дело его личное. Поэтому, даже в одном и том же драйвере, можно встретить различные комбинации команд:
STA ¤C08F,X / ORA ¤C08C,X
или
STA ¤C08D,X / LDA ¤C08C,X

Первая комбинация включает режим записи и сразу начинает скидывать первый байт (но защелка C/D уже должна быть включена в "1", например, процедурой проверки защиты записи), вторая же интересна тем, что не портит содержимое аккумулятора ЦПУ, выполняя переключение защёлки C/D (LDA просто читает из аккумулятора секвенсора только что записанное туда значение).

Кодирование битиков секвенсором (напомнию: "1" должна вызывать смену уровня, "0" - не менять линию записи) реализовано хитро: линия записи подключена к старшему биту указателя адреса команд секвенсора. Процедура секвенсора разделена на две три части: первая содержит 16 шагов и выполняется если старший бит аккумулятора = 1, вторая и третья части - 8 шагов и выполняются если старший бит аккумулятора = 0. Понятно, что когда исполняется длинная часть, старший бит адреса периодически меняет своё значение (как раз однажды за время записи одного бита), а две короткие части расположены таким образом, что во время их исполнения старший бит остаётся неизменным.

Чтобы следующая команда записи в аккумулятор попала в нужный такт секвенсора, ЦПУ должен выполнять её в момент, кратный 4-м своим тактам (т.е. 8 такта секвенсора - время записи одного бита). Так как байт, пока ещё, содержит 8 бит, очевидно, что в нормальном режиме ЦПУ должен засылать цифры раз в 32 своих такта. Если это время удлиннить (до 36 или 40 тактов), секвенсор, покончив с последним битом, начнёт генерировать нули (т.е. постоянный уровень на линии записи). Эти нули могут использоваться для того, чтобы во время чтения синхронизовать контроллер. Или можно использовать их и для чего нибудь ещё. Но помните: больше двух нулей подряд во время записи = мусор во время чтения.

Процедура чтения данных

Активируется комбинацией "C/D = 0" & "Write = 0". В этом режиме секвенсор выполняет довольно сложную программу, которая отличается у разных версий агатовского и эпловского железа. Но важно следующее:

Как это работает ?

Да, вот, собственно, именно так. Т.е. в точном соответствии с процедурами, выполняемыми секвенсором. Что важно:

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *