亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

Arduino Amiga 软盘读写器(V2.2)

组件和用品

Arduino UNO
× 1
SparkFun Arduino Pro Mini 328 - 5V/16MHz
× 1
电阻 1k ohm
× 1
面包板(通用)
× 1
跳线(通用)
× 1
SparkFun FTDI 基本突破 - 5V
× 1

应用和在线服务

Arduino IDE

关于这个项目

这个项目延续了我之前在 的磁盘阅读器项目的工作 https://create.arduino.cc/projecthub/projects/485582/

欲了解更多信息,请访问 http://amiga.robsmithdev.co.uk

  • 我的目标: 创建一种简单、廉价且开源的方式,在 Windows 10 中从 Amiga DD 软盘恢复和重写数据。
  • 我的解决方案: 一个 Arduino 草图 + 一个 Windows 应用程序(可以移植到其他操作系统 ) 确实有效!
  • 为什么: 为将来保留这些磁盘中的数据。此外,由于 Amiga 磁盘的写入方式,普通 PC 无法读取/写入它们。

写入数据 - 尝试 1

所以在能够成功读盘之后,我想如果你想保留原来的物理介质,你可能需要重新写盘。我想我会反过来解决这个问题,从软件开始(即:将 ADF 磁盘文件转换为 MFM 数据,以便接口写入不知何故 ).

所以我开始添加类来读取 ADF 磁盘,并将所有扇区编码为一个轨道。知道我可以通过将其反馈到解码部分来测试我创建的数据,我开始研究这个。在处理这个问题时,我决定尝试找出我的 Amiga 出了什么问题。毕竟,如果我没有任何真实,我就无法测试我创建的任何磁盘 测试它们。

拆开我的 A500+,我注意到它遇到了最常见的问题之一,时钟电池到处泄漏。所以我从板上拆下它并开始清理电路板。在此期间,我将整个机器拉出并开始清理 20 年的灰尘和污垢。我什至拆开软驱来清理它。

清洗的时候,我决定是时候摆脱泛黄了,所以我按照有关 Retr0brite 的信息进行了尝试。

然后我检查了主主板上的所有接头,发现电源连接器的连接松动,用烙铁进行了一些修补,并且和新的一样好。直到我对 Retr0brite 过程感到满意,才重新组装计算机。

与此同时,我继续研究写磁盘的代码。我想读取写保护线的状态,但无论我怎么设置它似乎都没有改变电压。因此,我将驱动器拆开,并跟踪从检测写保护状态的小开关到小 IC 的轨迹。到这里我猜想大概只有当你真正想写数据的时候输出才可用。

很多之后 实验中,我发现你需要拉 /WRITE_GATE 在启动驱动器以启用写入之前将引脚置于低电平。此时您可以获得写保护状态。我还注意到,虽然 /WRITE_GATE 低电平驱动器不会像以前那样关闭,直到该引脚恢复到默认的高电平状态。

Amiga 会一口气写出一首完整的曲目。内存中的一条轨道是11*512字节(5638字节),但是经过MFM编码并放入正确的AmigaDOS格式后,该轨道为14848字节。嗯,没有办法可以放入 Arduino 的 2k 内存,也没有办法放入 1k 的 EEPROM。我需要另一种方法。

我决定尝试在高优先级线程中一次发送 1 个字节的数据,并在发送下一个之前等待来自 Arduino 的响应字节。我将波特率更改为 2M 以减少字符之间的延迟。这意味着发送每个字符大约需要 5.5 uSec,接收一个字符需要 5.5 uSec。 Arduino 需要以 500khz 的频率写出 8 位,因此每 16 uSec 需要一个新字节。所以应该有时间,假设代码循环足够紧,操作系统不会延迟发送和接收太多。

这是一次彻底的、彻底的失败。整个读/写周期花费的时间太长,远远超过磁盘旋转一圈。 Arduino 端可能足够快,但操作系统响应不够快。读取磁盘之所以有效,是因为操作系统(在我的情况下为 Windows)会缓冲传入的数据,但是写入时,Windows 只会一次性发送所有数据,但因为我发送的速率远快于 Arduino 需要的速度,数据会丢失。这就是我决定采用这种双向确认流程的原因。

写入数据 - 尝试 2

此应用程序的软件流控制速度不够快。我决定研究硬件流控制。我注意到在 FTDI 分线板上有 CTS 和 DTR 引脚。这些代表清除发送数据终端就绪 .我注意到在连接分线板时,Arduino 板将 CTS 连接到 GND。

我也不知道这些引脚实际上在哪个方向,但经过一些实验,我发现 CTS 引脚可以从 Arduino 发出信号并被 PC 用来控制流量。通常这是使用循环缓冲区完成的,但在我的情况下,我不允许这样做,所以当我不需要数据时,我只需将其设置为“1”,而在需要时将其设置为“0”。

这意味着我现在可以只要求操作系统将字节作为一个块批量发送,并希望所有这些都在内核级别进行处理,以免被中断。

我有一个内部循环,输出 8 位中的每一位,但决定将其分解为 8 组命令可能是更好的时机。

这没有用。如果我允许代码在不实际运行磁盘写入部分的情况下运行,那么所有字节都被正确接收,但是在运行代码时,它没有并且正在接收的字节正在丢失。

我怀疑改变 CTX 线的状态并没有立即停止数据流,计算机可能仍会发送一两个字符。可能当我给 CTX 线路发信号时,它已经在发送下一个字符的过程中了。

写入数据 - 尝试 3

我不想有一个串行中断,因为我不希望任何写入时间被扭曲。我意识到在将每一位写入软盘驱动器之间,下一个 while 循环中将有许多 CPU 周期。我决定在每个位写入之间检查自 CTX 变高后是否接收到另一个字节并存储它。

我的理论是,当你提高 CTX 时,计算机可能已经在传输下一个字节的中间,因为你不能在中途停止它,那么在这个字节之后它会减半。这意味着我只需要在循环期间检查一个额外的字节,如果找到就使用它,而不是再次查看串行端口。

所以这似乎有效,并且 Arduino 完成了写入而没有丢失任何来自计算机的数据。现在唯一的问题是:它是否真的写入了任何数据,如果是,它是否有效?

此时我只编码了一个轨道,所以我决定运行整个算法来编码所有 80 个轨道。奇怪的事情正在发生。驱动头根本不动。读的时候还是这样,写的时候不行。

我发现为了来回移动驱动头,你首先必须抬起 /WRITE GATE 引脚,我怀疑这也是改变表面所必需的。一旦我添加了代码来执行此操作,驱动器头就会按预期移动。这确实有意义,并且可以防止在移动头部时意外写入曲目。

所以此时我写了一个我之前创建的磁盘映像,然后尝试读回它。什么都检测不到!要么我写的数据无效,要么我写的方式不对。

我决定将我正在创建的编码 MFM 扇区数据输入到我的扇区解码算法中,阅读器使用它来验证我生成的内容是正确和有效的,而且确实如此。我将数据写入磁盘的方式显然有问题。

写入数据 - 尝试 4

由于没有正确读取数据,我决定尝试几种不同的方法。我不确定 /WRITE DATA 引脚是否应该脉冲(如果是,脉冲多长时间)、切换或只是设置为原始数据值。我当前的实现使引脚脉冲。我无法在网上找到任何有关在写入时物理上假设如何操纵写入引脚的信息。

每次出现磁通反转时,读头都会向我们发送一个脉冲。我决定更改实现,以便将 WRITE DATA 设置为该位的值。那也没有用。所以我更改了代码以切换引脚的当前状态。仍然没有运气。

显然,这些方法之一一定是正确的。所以我决定再次拿出可靠的示波器来看看发生了什么。我决定将 MFM 模式 0xAA 连续写入轨道上的每个字节。二进制的 0xAA 是 B10101010,所以这会给我一个完美的方波,我可以监控所需的频率。

如果它没有看到所需频率的完美方波,那么我知道一定存在某种时序问题。

我连接了示波器,但惊讶地发现时间 完美的。然而,作为一个老式的示波器,我只能看到几个脉冲。示波器具有这种美妙的 x10“mag”模式。按下时,它会将时基增加 10,但更重要的是,您可以像在现代数字示波器上一样滚动浏览所有数据。

这里有些不对劲。看起来每 12 位左右,我最终得到了一段 “高” .

我发送的数据在某种程度上无效,或者每隔 12 位左右就会导致写入过程暂停。考虑到一个字节只有 8 位,12 是一个奇怪的数字。

考虑到这一点后,我想知道我是否回到了流量控制问题。我设计循环的方式是在我们等待一个之后接收到的任何杂散的额外字节。但它不够智能,无法防止每隔一个字节等待一次。我有两个选择,移动东西 进入中断,或修补循环。

我决定首先纠正循环的工作方式。该问题是由于等待来自计算机的下一个字节而导致的延迟。如果我们降低CTX并等待一个字节,当我们再次提高CTX时,另一个字节已经在路上了。

我更改了循环,以便在使用接收到的第二个字节时,Arduino 暂时将 CTS 拉低,然后再次拉高以允许发送另一个字符。这意味着在下一个循环中,我们已经收到了下一个字节,因此无需等待。

测试这产生了一个完美的方波:

这意味着编写曲目的所有时间都是完美的,这取决于实际 正在写入的数据。我决定让它运行几个轨道和侧面,然后再读一遍,看看它是否写得正确。我正在将 /WRITE_DATA 引脚设置为接收到的数据中的相应位值。

当读回数据时,它看起来没有被编码,但随后我跳到了磁盘的另一侧。果然有我的模式。我不知道为什么它只写入磁盘的一侧。

经过一番思考,我开始怀疑 /WRITE GATE 引脚是否真的像我想象的那样工作。碰巧的是,通过将引脚拉低,它可能会启用驱动器上的擦除头。如果是这种情况,那么我应该只在我实际写入时执行此操作,否则我可能会在磁盘旋转和擦除时在磁盘上产生噪音。

我更改了所有代码,以便 /WRITE GATE 仅在首次启动驱动器时使用,然后仅在写入循环期间才使用。那行得通!我现在正在向磁盘的两侧写入数据!

所以我再次尝试使用真正的 ADF 磁盘映像并让它完成。然后我使用阅读器部分来看看我是否可以读回它。有效!但是由于某种原因,读回这个磁盘需要相当长的时间。我没有收到任何 MFM 错误,但很难找到所有扇区。

我现在看有两种可能性:第一,数据实际上是否足够及时地写入;其次,磁盘真的可以在真正的 Amiga 中工作吗?

一想到我可能真的写了一个磁盘,我就很兴奋现在可以工作 A500+ 并放入磁盘。片刻之后,磁盘开始启动,然后显示著名的校验和错误消息。所以我在写东西 有效,但不一致。

我决定除非我能以更准确的速度读回数据,否则写磁盘是没有意义的。

读取数据(再次)

我想提高阅读质量,因为我对当前的实现不满意。当前的实现不允许脉冲在稍微奇怪的时间到达的足够灵活性。我需要一种新方法。

首先,我决定将读数与 /INDEX 脉冲同步。 Amiga 不需要它,但可能会在以后对我进行测试、写作和阅读时派上用场。

在对这个项目前半部分的评论中,有几个人建议我应该记录脉冲之间的时间,而不是我已经实施的方法。唯一的问题是将这些数据足够快地传送到 PC。如果我要为每个位发送一个字节,那么我很容易超过最大 2M 波特率。

我决定最好的办法是尝试理解数据。所以我决定让我最初使用的计数器自由运行,直到 255。然后我把代码放在一个循环中等待一个脉冲,这一点看到了多少时间过去了。

在理想情况下,最低可能的最小值是 32(对应于 2 uSec)。使用 MFM,您最多只能在一行中包含三个 0,因此该值应达到的最大值为 128。这意味着一行中最多有 4 个可能的组合。

我对几个磁盘进行了采样,以查看这些频率中的大部分位于何处,结果如下所示:

看看这个,我发现大多数点都在 52、89 和 120 的计数器附近。但是,这些点对我的驱动器有些特殊,因此不是一个好的指导方针。经过一些实验,我使用了以下公式:value =(COUNTER - 16) / 32 .当剪辑在 0 和 3 之间时,这给了我所需的输出。每 4 个,我就可以写出一个字节。

我突然想到,因为在 MFM 编码的比特流中不能有两个 '1',所以我可以安全地假设第一个值的任何内容都是无效的,并且可以被视为另一个 '01' 序列。下一部分是将 PC 接收到的数据解包并将其转换回 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 位之后回零,这正是我们需要的时候。这意味着只要我们以所需的计时器值写入位,我们就会精确地达到 500kbps。

我还查看了如何从串行端口读取数据。这是在每个位之间读取的,但这也需要尽可能短。经过一些实验,我实现了最短的工作块。

修改 Windows 代码以支持验证后,我现在准备再试一次。这次我知道如果磁盘验证正常,那么它应该可以在Amiga中正常工作。

所以我尝试写另一个磁盘。验证需要更长的时间。使用新算法,大约 95% 的曲目在第一次通过验证,只有剩下的 5% 需要再次重写。我对此很满意,然后将磁盘放入 Amiga。效果很好!

写入数据 - 尝试 6

在一些使用过它的人的反馈之后,很明显,即使在驱动器上进行了验证,也并不总是能生成完全可读的磁盘。软件可以完美地读回它们,但 Amiga 计算机会在这里和那里报告一些校验和错误。

我又看了一遍代码,想知道这是否是一个时间问题,并查看是否可以将其设置为中断驱动,但遗憾的是,由于每个位之间的时间很少,根本没有足够的时间进行中断通过保留您修改的寄存器等来实现这一点。

然后我回顾了编写代码。在写入一个完整字节后,代码可能会在定时器溢出回 0 之前循环回开始写入下一个字节,从而允许提前写入第一位。

我添加了一个小循环以确保不会发生这种情况,希望可以为遇到此问题的任何人解决此问题。

写入数据 - 尝试 7

在收到大量关于写入磁盘的校验和错误的报告后,我开始进行调查。起初我以为我将不得不从磁盘中查看 MFM 数据,但问题实际上要简单得多

查看 XCopy Pro 以查看校验和错误,它报告了代码 4 和 6,表示扇区标题和数据区域中的校验和错误。如果它只是数据区,那么我会假设它纯粹与写入轨道的最后几位有关,但事实并非如此。

我开始查看编写代码和每个轨道周围的填充,想知道我是否时不时覆盖轨道的开头,所以我将轨道后填充从 256 字节大量减少到 8。令我惊讶的是我的验证然后排除了大量错误。

这让我想知道实际问题是否是我没有编写足够的数据。我开始向 Arduino 添加一个 Track Erase 命令,该命令会将 0xAA 模式写入整个轨道,然后再写入我的轨道。令我惊讶的是,XCopy 给了它 100% 的赞许。所以希望这能解决这个问题。

诊断

我从成功完成这个项目的人那里得到了很多反馈,无论是完全有效还是无效。我决定在代码中构建一个诊断模块,以帮助任何无法正常工作的人。

诊断选项包含一些额外的命令,供 Arduino 处理,以及运行以确保一切正确连接的一系列事件。

那么接下来是什么?

整个项目在 GNU 通用公共许可证 V3 下免费和开源。如果我们想有任何希望保留Amiga,那么我们不应该为了特权而互相扯掉。此外,我想回馈给我曾经工作过的最好的平台。我也希望人们能够开发它并进一步发展并继续分享。

当前的写入解决方案不是 Arduino UNO 上的一个选项,除非您使用单独的 FTDI/串行分线板,所以我的下一个任务是让它在上面工作(可能使用 23K256 IC 缓冲轨道,然后再将其写入到磁盘)。

我还想看看其他格式。 ADF 文件很好,但它们只适用于 AmigaDOS 格式的磁盘。有许多具有自定义复制保护和非标准扇区格式的标题,这种格式根本无法支持。我收到了一些关于此的非常有用的信息,但目前没有很多磁盘可供测试。

根据维基百科,还有另一种磁盘文件格式,即 FDI 格式。一种通用格式,有据可查。这种格式的优点是它尝试尽可能接近原始存储轨道数据,因此希望能解决上述问题!

我还遇到了软件保护协会,特别是 CAPS(正式名称为 Classic Amiga Preservation Society ) 和它们的 IPF 格式。读了一点点后,我很失望;全都关门了,感觉他们只是用这种格式来卖他们的读盘硬件。

所以我的重点将放在 FDI 格式上。我唯一关心的是数据完整性。不会有任何校验和供我检查以查看读取是否有效,但我有一些想法可以解决这个问题!

代码

草图和 Windows 应用程序源
Arduino Sketch 和示例 Windows 应用程序源代码 https://github.com/RobSmithDev/ArduinoFloppyDiskReader

示意图

Arduino Pro Mini 电路 Arduino UNO 电路

制造工艺

  1. 动画
  2. 软盘
  3. NeoPixel Ring 的陀螺仪乐趣
  4. Arduino Spybot
  5. FlickMote
  6. 自制电视 B-Gone
  7. Arduino 游戏控制器
  8. 云服装
  9. 主时钟
  10. Pixie:基于 Arduino 的 NeoPixel 手表
  11. 找到我
  12. Arduino Amiga 软盘阅读器 (V1)