Сайт посвящен ПЭВМ АГАТ: Передовица » Hardware » ДЗУ » Исследование КНГМД 840 » Программа декодирования данных чтения

© 2004-2021 AgatComp

Форум

Общие сведения

Software

Hardware

Агат ↔ PC

Эмуляторы/утилиты

Люди

Макулатура

Всякая всячина

Ссылки

Контакты

Помощь сайту

Последние обновления

Программа декодирования данных чтения

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

         data=0        |         PULSE!
00: 		       |    	      go 04 :00
01: 		       |    	      go 04 :01

02: 		       |    	      go 04 :02		фаза Sync
03: 	   <BC=0       |    	<BC=c	    :03
04: 	   <BC=0       |    	<BC=c	    :04
05: 	   <BC=0       |    	<BC=c stop  :05
06: 	   <BC=0       |    	<BC=c go 05 :06
07: ->1 BC>	 go 18 |    	      go 05 :07

08: 		       |    	      go 05 :08		фаза 2
09: 		       |    	      go 2B :09
0A: 		       |    	      go 2C :0A
0B: 		       |    	      go 2C :0B
0C: 		       |    	      go 2D :0C
0D: 		       |    	      go 2D :0D
0E: 		       |    	      go 2E :0E
0F: 		 go 30 |    	      go 2F :0F

10: 		       |    	      go 03 :10		фаза 1
11: 		       |    	      go 03 :11
12: 		       |    	      go 04 :12
13: 		       |    	      go 04 :13
14: 		       |    	      go 05 :14
15: 		       |    	      go 05 :15
16: 		       |    	      go 06 :16
17: ->0 BC>	 go 28 |    	      go 06 :17

18: 	   <BC=c       |    	<BC=c go 02 :18		фаза 0
19: 		       |    	      go 02 :19
1A: 		       |    	      go 03 :1A
1B: 		       |    	      go 03 :1B
1C: 		       |    	      go 03 :1C
1D: 		       |    	      go 04 :1D
1E: 		       |    	      go 04 :1E
1F: 		 go 10 |    	      go 04 :1F

20: 		       | ->0 BC>      go 2A :20		фаза 5
21: 		       | ->0 BC>      go 2A :21
22: 		       | ->0 BC>      go 2B :22
23: 		       | ->0 BC>      go 2B :23
24: 		       | ->0 BC>      go 2B :24
25: 		       | ->0 BC>      go 2C :25
26: 		       | ->0 BC>      go 2C :26
27: ->0 BC>	       | ->0 BC>      go 2C :27
28: 	   <BC=c go 09 |    	<BC=c go 04 :28

29: 		       |    	      go 04 :29

2A: 	   <BC=c       |    	<BC=c go 04 :2A		фаза 31
2B: 	   <BC=c       |    	<BC=c go 04 :2B
2C: 	   <BC=c       |    	<BC=c go 05 :2C
2D: 		       |    	      go 05 :2D
2E: 		       |    	      go 05 :2E
2F: 		 go 20 |    	      go 05 :2F

30: 		       |    	      go 03 :30		фаза 30
31: 		       |    	      go 04 :31
32: 		       |    	      go 04 :32
33: 		       |    	      go 04 :33
34: 		       |    	      go 05 :34
35: 		       |    	      go 05 :35
36: 		       |    	      go 05 :36
37: ->0 BC>	       |    	      go 06 :37

38: 	   <BC=c       | ->1 BC><BC=c go 03 :38		фаза 4
39: 		       | ->1 BC>      go 04 :39
3A: 		       | ->1 BC>      go 04 :3A
3B: 		       | ->1 BC>      go 04 :3B
3C: 		       | ->1 BC>      go 05 :3C
3D: 		       | ->1 BC>      go 05 :3D
3E: 		       | ->1 BC>      go 05 :3E
3F: 		 stop  | ->1 BC>      go 06 :3F

Здесь только две колонки. Фактически их четыре - как и в режиме записи, но первая совпадает с третьей, а вторая - с четвёртой, поэтому опустим их. Иными словами - программа не зависит от сигнала "следующий байт". Левая колонка соответствует отсутствию единиц на входе секвенсора, правая - появлению единицы.

Фактически, формирователь на микросхемах D5, D13, D8 будет отправлять на секвенсор поток единиц, изредка перемежающихся нулями в тех местах, где при записи на дисковод была отправлена единица. Мы его уже рассматривали ранее. Но, для удобства, здесь об этой инверсии пока забудем.

Справа и слева, как и в программе записи, указаны номера шагов. Обозначения команд:

  • Wph - сигнал записи кода из ПЗУ D25 в счётчик D26. Этого обозначения нет в программе, но, вообщем-то, сигнал всё равно вырабатывается на шагах ¤00..0F и ¤20..2F. Так что во время чтения на выходе данных записи будет появляться нечто, вполне предсказуемое.
  • go XX - переход на шаг XX. Если этой команды в строке нет - это переход на следующую строку.
  • ->n - команда сдвига в регистр D21 значения n. D22 также сдвигается, но для чтения это не важно.
  • BC> - ставится флажек о том, что на следующем шаге будет выполнена модификация счётчика бит D23. Следующий шаг может быть строкой ниже либо в том месте, куда произойдёт переход по go и/или по изменению входящих данных.
  • <BC=0 - если на предыдущем шаге был BC> то на этом шаге будет BC будет сброшен на ноль.
  • <BC=c - если на предыдущем шаге был BC> то на этом шаге будет BC будет увеличен или сброшен на 8 (если активен сигнал "следующий байт").
  • stop - в этой команде есть go на саму себя - пауза. Секвенсор может выйти из паузы при изменении входных данных.

Здесь важно обратить внимание на то, что <BC=0 выполняется только если перед ним была команда BC>. Взгляните на шаги 3-6 - BC=0 есть только тут. Но выполняется она не всегда ! Это было понято мной отнюдь не сразу.

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

Не все шаги входят в какую либо фазу, например: ¤00, 01, 29. Они не используются и могут быть выполнены только при переключении секвенсора из режима записи, если программа в этот момент выполняла переход на такой адрес. Кстати, ведь шаг ¤00 в программе записи не используется? Ну, значит этот шаг вообще никогда не выполняется. В таких шагах главное - чтобы секвенсор мог выйти из них на нормальный поток исполнения.

Распутывать программу я предлагаю с фазы 4, она находится в самом конце. Прямо с шага ¤3F. Дело в том, что здесь есть команда stop, т.е. дойдя до неё и видя на входе ноль, секвенсор будет "висеть" на этом шаге, дожидаясь единицы.

Как только на входе появится единица, произойдёт переход на шаг ¤3F в правой колонце, где нас ожидает команда BC>. Дальше последует переход на шаг ¤06 и там будет выполнен сброс счётчика <BC=0. Мы попали в фазу Sync. Секвенсор сгенерировал событие синхросбоя и начал отсчёт бит.

А если бы единица появилась на любом другом шаге фазы 4 ? Почти ничего не меняется: переход в фазу Sync, разве что чуть раньше или чуть позже. Заметьте: секвенсор всегда стремится сделать переход примерно в середину очередной фазы: из 8 возможных шагов он делает переход на шаги 3-6. Таким образом, если единичка в потоке данных немного отклонилась от центра фазы, секвенсор немного поправит свою работу таким образом, чтобы следующий бит появился поближе к центру фазы.

Посмотрим дальше на фазу Sync. Что будет, если какие-то странные единички будут появляться на этом шагу ? Вообще-то мы знаем, что в MFM не допустимы две соседних единицы. Но если всё таки они появятся ? В этом случае мы смотрим правую колонку - там стоят переходы на шаги ¤04 и 05. Т.е. исполнение будет крутиться внутри фазы Sync.

Допустим, что в фазе Sync единиц не поступало. Тогда дальше программа доходит до шага ¤07 и тут секвенсор задвигает в регистр D21 единицу, а также делает переход на шаг ¤18. Здесь начинается фаза 0. Она пустая, заканчивается либо переходом на шаг ¤10 (фаза 1), если единичек не поступало, либо на фазу Sync, если единичка появилась.

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

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

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

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

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

Таким образом последовательности бит: 01 - займет три фазы (одна пройдёт целиком 8 шагов, вторая примерно половину и третья дополнит вторую до 8 шагов), 10 - тоже три фазы, 00 - две фазы, 11 - запрещена.

Попробуем проанализировать простые случаи. Например, исполнение попало в фазу Sync. Оно туда попадает из фазы 4, если только что произошел синхросбой. В фазе 4 была обнаружена единица (мы это недавно выше рассматривали), в фазе Sync мы уже единиц не ожидаем. В сумме пройденные шаги фазы 4 и оставшиеся шаги фазы Sync составят примерно 8. Но если всё таки единица в фазе Sync возникнет ? Тогда, как мы помним по программе, произойдет переход обратно в фазу Sync. Этот переход в нормальном потоке байт невозможен, но программой предусмотрен. На диаграмме он показан справа от фазы Sync и перечёркнут рыжим крестом. На диаграмме есть ещё четыре таких же ненормальных перехода.

Заметьте: эти переходы явно свидетельствуют о какой-то ошибке в потоке данных, однако программой секвенсора не предусмотрена фиксация такой ошибки. Это плохо, но следует знать, что так есть. Между тем, это было бы несложно исправить. Например, в фазе 31 ошибкой является появление единицы и, в этом случае, предусмотрен переход на фазу Sync. Но стоило бы добавить в правую колонку фазы 31 команду BC> - и переход бы вызывал синхросбой. Согласно документации, драйвера должны считать неверно прочитанными участки, на которых регистрируется синхросбой. И это проверяется драйверами. (А может быть я в чём-то ошибся и такая регистрация всё таки есть? Проверьте...)

Теперь попробуем от фазы 4 рассмотреть последовательность 10101010. Во время фазы 4 возникает единица, поток исполнения попадает в фазу Sync, регистрируется синхросброс (сброс счётчика бит в 0), заканчивается фаза Sync и начинается фаза 0. Она проходит до конца, так как при нуле поток идёт вниз от фазы. Исполнение уходит на фазу 1, вновь возникает единица, переход на фазу Sync, но теперь уже, так как при переходе из фазы 1 нет команды BC>, сброса счётчика бит не происходит. Заканчивается фаза Sync, следующий бит 0, поэтому минуем фазу 0 вниз, к фазе 1 опять возникает единичка на входе и цикл повторяется.

Что получается ? Фазы Sync, 0, 1 образуют цикл приёма и раскодирования последовательности единиц. Обводим его жёлтым цветом.

Если таким же образом проследить фазы 2, 31 и 5, то будет видно, что это цикл приёма и раскодирования последовательности нулей. Смена циклов в нормальном режиме приёма происходит либо при переходе с фазы 1 в фазу 2 либо при переходе с фазы 2 на фазу 30 и далее на фазу Sync.

Теперь легко увидеть, что такое синхросбой с точки зрения программы чтения. Мы это уже и так знаем, но по диаграмме можно проверить это ещё раз: получив единицу с переходом между фазами 4 и Sync предположим, что дальше идут нули. Первый ноль попадает в фазу 0, второй в фазу 1, третий в фазу 2 и четвёртый в фазу 30. Если бы в фазе 30 возникла единица - это было бы 10001, которая может быть валидной. Но четвёртый ноль однозначно приводит к регистрации синхросбоя.

Есть и другой путь: в фазе 2 была единица, произошел переход в фазу 31, затем были только нули. Первый попал в фазу 5, второй в фазу 2, третий в фазу 30... Синхросбой неизбежен.

Остаётся последнее обозначение на диаграмме: сбоку от фаз есть пометки sync, dat, sync2 и dat2. Программа секвенсора ожидает в каждой фазе какой-то бит, но разобрав диаграмму становится ясно - какой именно. sync и dat - бит синхронизации и бит данных, а sync2 и dat2 стоят рядом с фазами, на которые произойдёт переход, если соответствующий бит в предыдущей фазе окажется единичным. Например, фаза 2 обозначена как sync, и если она поймает единичку, то выполнение продолжится с середины фазы 31 - её и обозначаем sync2.

Вот и всё. Надеюсь, вам, как и мне, понравилась это путешествие в удивительную кроличью нору.