Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Устройство чтения / записи гибких дисков Arduino Amiga (V2.2)

Компоненты и расходные материалы

Arduino UNO
× 1
SparkFun Arduino Pro Mini 328 - 5 В / 16 МГц
× 1
Резистор 1 кОм
× 1
Макет (общий)
× 1
Перемычки (общие)
× 1
SparkFun FTDI Basic Breakout - 5V
× 1

Приложения и онлайн-сервисы

IDE Arduino

Об этом проекте

Этот проект является продолжением моего предыдущего проекта чтения с дисков на https://create.arduino.cc/projecthub/projects/485582/

Для получения дополнительной информации посетите http://amiga.robsmithdev.co.uk

  • Моя цель: Создать простой, дешевый способ с открытым исходным кодом для восстановления и перезаписи данных с дискет Amiga DD и на них из Windows 10.
  • Мое решение: Эскиз Arduino + приложение Windows ( которое может быть перенесено на другие ОС ), что действительно работает!
  • Почему: Чтобы сохранить данные с этих дисков на будущее. Кроме того, обычный ПК не может читать / записывать диски Amiga из-за того, как они записаны.

Запись данных - попытка 1

Итак, после того, как я успешно смог читать диски, я решил, что если вы хотите сохранить исходный физический носитель, вы, возможно, захотите снова записать диски. Я решил, что буду работать в обратном порядке, начиная с программного обеспечения (то есть:преобразование файлов диска ADF в данные MFM, чтобы интерфейс мог писать каким-то образом ).

Итак, я начал с добавления классов для чтения ADF-диска и кодирования всех секторов как одной дорожки. Зная, что я потенциально могу проверить данные, которые я создал, вернув их в часть декодирования, я начал работу над этим. Работая над этим, я решил попытаться выяснить, что не так с моей Amiga. В конце концов, я не могу протестировать созданные мной диски, если у меня нет ничего настоящего чтобы проверить их.

Разбирая свой A500 +, я заметил, что у него была одна из самых распространенных проблем - повсюду протекала батарея часов. Я снял это с платы и приступил к ее чистке. При этом я вытащил всю машину и приступил к уборке 20-летней пыли и грязи. Я даже разобрал дисковод для гибких дисков, чтобы почистить его.

Во время чистки я решил, что пора избавиться от пожелтения, поэтому следил за информацией о Retr0brite и попробовал его.

Затем я проверил все соединения на основной материнской плате и обнаружил неплотное соединение у разъема питания, несколько доработок с помощью паяльника и все как новенькое. Я подождал, пока меня не устроит процесс Retr0brite, прежде чем собирать компьютер.

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

После много экспериментов, я обнаружил, что вам нужно вытащить / WRITE_GATE pin LOW перед раскруткой диска, чтобы разрешить запись. На этом этапе вы можете получить статус защиты от записи. Я также заметил, что в то время как / WRITE_GATE был низким, привод не отключался, как раньше, до тех пор, пока этот вывод не вернулся в свое ВЫСОКОЕ состояние по умолчанию.

Амига записывала весь трек за один присест. Размер дорожки в памяти составляет 11 * 512 байт (5638 байт), однако после MFM-кодирования и установки в правильный формат AmigaDOS дорожка обрабатывается как 14848 байт. Ну, нет способа, который бы поместился ни в 2 КБ памяти Arduino, ни в его 1 КБ EEPROM. Мне нужен был альтернативный метод.

Я решил, что попытаюсь отправить данные по 1 байту в потоке с высоким приоритетом и дождаться байта ответа от Arduino перед отправкой следующего. Я изменил скорость передачи данных на 2M, чтобы уменьшить задержку между символами. Это означало, что для отправки каждого символа требовалось примерно 5,5 мксек, а для получения одного обратно - 5,5 мкс. Arduino нужно будет записать 8 бит на частоте 500 кГц, поэтому ему потребуется новый байт каждые 16 мкс. Так что должно быть время, при условии, что цикл кода достаточно жесткий, а операционная система не слишком сильно задерживает отправку и получение.

Это был полный провал. Весь цикл чтения / записи занял слишком много времени, превышая один оборот диска. Сторона Arduino, вероятно, была достаточно быстрой, но ОС была недостаточно отзывчивой. Чтение дисков работает, потому что ОС (Windows в моем случае) буферизует поступающие данные, но при записи Windows просто отправит их все за один раз, но поскольку скорость, с которой я отправляю, намного выше, чем это нужно для Arduino, данные будут потеряны. Вот почему я выбрал этот двусторонний процесс подтверждения.

Запись данных - попытка 2

Программное управление потоком для этого приложения было недостаточно быстрым. Я решил исследовать аппаратное управление потоком. Я заметил, что на плате отвода FTDI есть вывод CTS и DTR. Это означает Clear To Send . и Готовность к работе с терминалом данных . Я заметил, что пока коммутационная плата была подключена, плата Arduino подключила CTS к GND.

Я также не знал, в каком направлении на самом деле были эти выводы, но после некоторых экспериментов я обнаружил, что вывод CTS может передаваться от Arduino и использоваться ПК для управления потоком. Обычно это делается с использованием кольцевого буфера, но в моем случае я не мог этого допустить, поэтому я просто установил для него значение «1», когда мне не нужны данные, и «0», когда они нужны.

Теперь это означало, что я мог просто попросить ОС массово отправить байты одним блоком и надеяться, что все это будет обработано на уровне ядра, чтобы его не прерывали.

У меня был внутренний цикл, который выводил каждый бит из 8 бит, но решил, что, вероятно, было бы лучше разбить его на 8 наборов команд вместо этого.

Это не сработало. Если я разрешил запуск кода без фактического выполнения части записи на диск, то все байты были получены правильно, но при запуске кода этого не произошло, и полученные байты терялись.

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

Запись данных - попытка 3

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

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

Так что, похоже, это сработало, и Arduino завершил запись без потери данных с компьютера. Единственными вопросами теперь были:записаны ли на самом деле какие-либо данные, и если да, то действительны ли они?

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

Я обнаружил, что для того, чтобы двигать головку привода вперед и назад, вам сначала нужно было поднять штифт / WRITE GATE, я подозревал, что это необходимо также для изменения поверхности. Как только я добавил код для этого, головка привода двигалась, как и ожидалось. Это имело смысл и предотвратило случайное написание треков при перемещении головы.

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

Я решил скормить закодированные данные сектора MFM, которые я создавал, в свой алгоритм декодирования сектора, используемый читателем для проверки того, что то, что я генерировал, было правильным и действительным, и это было так. Что-то явно было не так с тем, как я записывал данные на диск.

Запись данных - попытка 4

Поскольку данные не считывались правильно, я решил попробовать несколько разных подходов. Я не был уверен, должен ли вывод / WRITE DATA быть импульсным (и если да, то как долго), переключаться или просто устанавливать значение необработанных данных. Моя текущая реализация пульсировала булавкой. Мне не удалось найти в Интернете никакой информации о том, как физически можно было манипулировать булавкой записи при записи.

Считывающая головка будет посылать нам импульс каждый раз, когда происходит изменение направления потока. Я решил изменить реализацию так, чтобы WRITE DATA был просто установлен на значение бита. Это тоже не сработало. Поэтому я изменил код, чтобы переключить текущее состояние вывода. По-прежнему не повезло.

Ясно, что один из этих подходов должен был быть правильным. Поэтому я решил снова достать проверенный осциллограф, чтобы посмотреть, что происходит. Я решил постоянно записывать шаблон MFM 0xAA в каждый байт дорожки. 0xAA в двоичном формате - это B10101010, так что это дало бы мне идеальную прямоугольную волну, которую я мог бы отслеживать на предмет требуемой частоты.

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

Я подключил прицел, но был удивлен, увидев, что время было идеально. Однако, будучи старым прицелом, я не мог видеть больше, чем несколько импульсов. У прицела был замечательный 10-кратный «магазинный» режим. При нажатии он увеличивал временную развертку на 10, но, что более важно, позволял прокручивать все данные так же, как на современном цифровом осциллографе.

Что-то здесь было не так. Похоже, каждые 12 битов я получал период только "высокий" .

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

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

Я решил сначала попытаться исправить работу цикла. Проблема возникла в результате задержки, вызванной ожиданием следующего байта от компьютера. Если мы опустили CTX и ждали байта, к тому времени, когда мы снова подняли CTX, другой байт уже был в пути.

Я изменяю цикл так, чтобы, когда был использован второй полученный байт, Arduino на мгновение переводил CTS в низкий, а затем снова в высокий уровень, чтобы разрешить отправку другого символа. Это означало, что в следующем цикле мы уже получили бы следующий байт, поэтому ожидания не требовалось.

При тестировании получилась идеальная прямоугольная волна:

Это означало, что все время для написания трека было идеальным, просто до фактического данные, которые были записаны. Я решил пропустить это несколько треков и сторон, а затем перечитал его, чтобы убедиться, что он написан правильно. Я устанавливал вывод / WRITE_DATA на соответствующее битовое значение из полученных данных.

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

После некоторого размышления я начал задаваться вопросом, действительно ли пин / WRITE GATE не работает так, как я думал. Оказалось, что, потянув штифт ниже, можно активировать стирающую головку на приводе. Если бы это было так, то мне следовало бы делать это только тогда, когда я действительно писал, иначе у меня может возникнуть шум на диске, когда он вращается и стирается.

Я изменил весь код так, что / WRITE GATE использовался только при первом запуске диска, а позже только буквально во время цикла записи. Это сработало! Теперь я записывал данные на обе стороны диска!

Итак, я попробовал еще раз с реальным образом диска ADF и позволил этому завершиться. Затем я использовал читательскую часть, чтобы посмотреть, смогу ли я прочитать ее. Это сработало! Но почему-то на то, чтобы прочитать этот диск обратно, потребовалось довольно много времени. Я не получал ошибок MFM, но мне было трудно найти все сектора.

Теперь у меня были две возможности:во-первых, действительно ли данные были записаны достаточно своевременно; а во-вторых, действительно ли будет работать диск на настоящей Амиге?

Я был слишком взволнован мыслью, что, возможно, на самом деле написал диск, я загрузил теперь работает A500 + и вставьте диск. Через несколько мгновений диск начал загружаться, а затем отображалось известное сообщение об ошибке контрольной суммы. Итак, я писал кое-что действительный, но непоследовательный.

Я решил, что если я не смогу считывать данные с гораздо более точной скоростью, запись на диск бессмысленна.

Чтение данных (снова)

Я хотел улучшить качество чтения, так как меня не устраивала текущая реализация. Текущая реализация не обеспечивала достаточной гибкости для того, чтобы импульсы приходили в несколько странное время. Мне нужен был новый подход.

Во-первых, я решил синхронизировать показания с импульсом / INDEX. Это не требуется для Amiga, но может пригодиться мне позже при тестировании, написании и чтении.

Несколько человек в комментариях к первой половине этого проекта предложили мне записывать время между импульсами, а не метод, который я реализовал. Единственная проблема заключалась в том, что данные передавались на ПК достаточно быстро. Если бы я отправлял по байту для каждого бита, я мог бы легко превысить максимальную скорость 2 Мбод.

Я решил, что лучше всего будет попытаться немного разобраться в данных. Поэтому я решил позволить счетчику, который я использовал изначально, работать свободно, вплоть до 255. Затем я поместил код в цикл, ожидая импульса, и в этот момент я увидел, сколько времени прошло.

В идеальной ситуации минимально возможное минимальное значение будет 32 (соответствует 2 мкс). С MFM вы могли иметь не более трех 0 в строке, поэтому максимальное значение, которое должно достичь это значение, составляло 128. Это означало, что было максимум 4 возможных комбинации подряд.

Я пробовал несколько дисков, чтобы увидеть, где находится большинство этих частот, и результаты можно увидеть ниже:

Глядя на это, я нахожу большинство точек вокруг счетчика 52, 89 и 120. Однако они были в некоторой степени специфичны для моего драйва и, следовательно, не были хорошим ориентиром. После некоторых экспериментов я использовал следующую формулу: value =(COUNTER - 16) / 32 . При ограничении между 0 и 3 это дало мне требуемый результат. Каждые 4 из них, и я мог записать байт.

Мне пришло в голову, что, поскольку у вас не может быть двух единиц вместе в битовом потоке, закодированном в MFM, я могу с уверенностью предположить, что что-либо для первого значения недопустимо и может рассматриваться как другая последовательность «01». Следующей частью было распаковать эти данные, когда они были получены ПК, и превратить их обратно в данные MFM. Это было просто, поскольку 00 не могло произойти, 01 означало запись «01», 10 означало запись «001», а 11 означало запись «0001». Я попробовал это сделать, и, к моему удивлению, мои результаты оказались на 100% успешными. Пробовал и еще с несколькими дисками, 100%! Теперь у меня был очень надежный ридер.

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

Запись данных - попытка 5

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

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

Оказалось, что отчасти это произошло из-за того, как я работал с последовательным портом, а отчасти из-за использования таймера. Я ждал, пока таймер достигнет значения 32, записал бит, а затем сбросил его. Я изменил его, поэтому мне не пришлось изменять значение счетчика таймера.

Я бы записал первый бит, когда счетчик достигнет 16, затем следующий, когда он достигнет 48 (16 + 32), и следующий, когда он достигнет 80 (16 + 32 + 32) и так далее. Timer2, состоящий всего из 8 бит, возвращается к нулю после 8-го бита, как раз тогда, когда нам это было нужно. Это означало, что до тех пор, пока мы записываем бит при требуемом значении таймера, мы будем иметь ровно 500 кбит / с.

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

После изменения кода Windows для поддержки проверки я был готов повторить попытку. На этот раз я знал, что если диск проверен правильно, то он должен нормально работать в Амиге.

Итак, я попытался записать еще один диск. С проверкой потребовалось больше времени. С новым алгоритмом около 95% треков прошли проверку с первого раза, и только оставшиеся 5% пришлось переписать еще раз. Я был доволен этим и вставил диск в Амигу. Сработало отлично!

Запись данных - попытка 6

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

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

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

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

Запись данных - попытка 7

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

Глядя на XCopy Pro, чтобы увидеть ошибки контрольной суммы, он сообщил коды 4 и 6, означающие ошибки контрольной суммы в заголовках секторов и областях данных. Если бы это была просто область данных, я бы предположил, что это было связано с записью последних нескольких бит трека, но это не так.

Я начал смотреть на код записи и отступы вокруг каждой дорожки, задаваясь вопросом, не перезаписываю ли я время от времени начало дорожки, поэтому я массово уменьшил отступы после дорожки с 256 байт до 8. К моему удивлению, моя проверка затем выбросил кучу ошибок.

Это заставило меня задуматься, действительно ли проблема в том, что я пишу недостаточно данных. Я решил добавить в Arduino команду удаления дорожки, которая будет записывать шаблон 0xAA на всю дорожку, а затем записывать мою дорожку. К моему удивлению, XCopy дал ему 100% высокую оценку. Надеюсь, проблема решена.

Диагностика

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

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

Итак, что дальше?

Весь проект бесплатный и с открытым исходным кодом под лицензией GNU General Public License V3. Если мы хотим иметь хоть какую-то надежду на сохранение Амиги, мы не должны грабить друг друга ради этой привилегии. Кроме того, я хочу вернуть лучшую платформу, над которой я когда-либо работал. Я также надеюсь, что люди разовьют эту идею, пойдут дальше и продолжат делиться.

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

Еще хочу посмотреть на другие форматы. Файлы ADF хороши, но они работают только с дисками, отформатированными AmigaDOS. Есть много заголовков с настраиваемой защитой от копирования и нестандартными форматами секторов, которые просто не поддерживаются этим форматом. Я получил очень полезную информацию по этому поводу, но в настоящее время у меня не так много дисков для тестирования.

Согласно Википедии, существует еще один формат дисковых файлов - формат FDI. Универсальный формат, который хорошо задокументирован. Преимущество этого формата заключается в том, что он пытается сохранить данные трека как можно ближе к оригиналу, поэтому, надеюсь, устранит указанные выше проблемы!

Я также наткнулся на Общество сохранения программного обеспечения, в частности, CAPS (формально Classic Amiga Preservation Society ) и их формат IPF. После небольшого чтения я был очень разочарован; все закрыто, и казалось, что они просто использовали этот формат для продажи своего оборудования для чтения дисков.

Так что мое внимание будет сосредоточено на формате прямых иностранных инвестиций. Меня беспокоит только целостность данных. Мне не нужно будет проверять контрольные суммы, чтобы убедиться, что чтение было правильным, но у меня есть несколько идей, чтобы решить эту проблему!

Код

Эскиз и исходный код приложения Windows
Arduino Sketch и пример исходного кода приложения Windows https://github.com/RobSmithDev/ArduinoFloppyDiskReader

Схема

Схема для Arduino Pro Mini Схема для Arduino UNO

Производственный процесс

  1. Анимация
  2. Дискета
  3. Удовольствие от гироскопа с кольцом NeoPixel
  4. Arduino Spybot
  5. FlickMote
  6. Самодельный телевизор B-Gone
  7. Игровой контроллер Arduino
  8. Костюм облака
  9. Основные часы
  10. Считыватель гибких дисков Arduino Amiga (V1)