基于 Arduino 的 Amiga 软盘读写器 —— Version 2.2
所需组件与物料
- Arduino UNO × 1
- Arduino Pro Mini 328 - 5V/16MHz × 1
- 1kΩ 电阻 × 1
- 面包板 × 1
- 杜邦线若干
- FTDI Basic Breakout - 5V × 1
所需软件
- Arduino IDE
项目背景
本项目延续了我之前的软盘读取项目: Arduino Project Hub 原项目
更多详情请访问: amiga.robsmithdev.co.uk
- 目标: 创建一个简单、低成本、开源的方案,在 Windows 10 下读写 Amiga DD(双密度)软盘数据。
- 方案: Arduino 固件 + Windows 应用程序(可移植到其他操作系统),且真正可用!
- 初衷: 为未来保存这些磁盘上的数据。普通 PC 因写入方式不同,无法直接读写 Amiga 磁盘。
写入数据 —— 尝试 1:软件流控
成功读取磁盘后,我想实现反向写入。从软件层面入手:将 ADF 磁盘镜像转换为 MFM 编码数据供接口写入。我添加了读取 ADF 并将所有扇区编码为一磁道的类,并计划用解码器验证生成的数据。
与此同时,我尝试修复手头的 Amiga A500+ 以便测试写入的磁盘。拆机发现时钟电池漏液腐蚀主板,清理焊点、除尘、甚至用 Retr0brite 处理发黄外壳,最终修复了电源接口附近的虚焊点。
代码方面,我发现必须在启动驱动器前将 /WRITE_GATE 引脚拉低才能启用写入并读取写保护状态。Amiga 一次写入整个磁道(11×512 字节 = 5632 字节),MFM 编码后扩展为 14848 字节,远超 Arduino 2KB RAM 和 1KB EEPROM 容量。
我尝试用高优先级线程逐字节发送并等待 Arduino 回复(波特率 2M),理论上每字节 16μs,但 Windows 调度延迟导致完全失败——读取时 OS 缓冲输入尚可,写入时数据发送过快丢包,双向确认机制反而拖慢流程。
写入数据 —— 尝试 2:硬件流控 (CTS/DTR)
改用 FTDI 模块的 CTS(Clear To Send)引脚进行硬件流控。实验发现 Arduino 可控制 CTS 电平,PC 端据此控制发送。我将 CTS 设为高电平表示“不接收数据”,低电平表示“可接收”,期望 OS 内核级处理批量发送。
将逐位输出循环展开为 8 条指令以优化时序,但仍失败:不运行写入逻辑时通信正常,一旦运行写入代码即丢字节。推测 CTS 信号切换不够快,PC 已开始发送下一字节。
写入数据 —— 尝试 3:利用写入间隙缓冲单字节
不想用串口中断干扰写入时序。观察到写入每位之间有 CPU 空闲周期,决定在每位写入间隙检查是否有新字节到达(CTS 拉高后 PC 可能已发出一个字节),暂存备用。
此法通过,Arduino 无丢包完成写入。但读回数据全为乱码。经验证编码算法无误,问题出在写入物理层面。编码全 80 磁道测试时发现磁头不移动——读取时正常。发现必须先拉高 /WRITE_GATE 才能移动磁头(防止移动时误写)。
写入真实 ADF 镜像后读回仍无数据。示波器检测写入 0xAA 模式(应产生完美方波),发现每 12 位出现一次异常高电平——流控仍有问题:每两字节需等待一次,导致周期性停顿。
写入数据 —— 尝试 4:优化流控时序
修改循环:使用第二个字节后,Arduino 短暂拉低再拉高 CTS,允许 PC 发送下一字节,下一轮循环直接读取无需等待。示波器显示完美方波!
但读回数据仅写入磁盘一面。推测 /WRITE_GATE 拉低可能触发擦除头,导致另一面噪声。修改代码:仅在启动驱动器和写入循环期间拉低该引脚。双面写入成功!
写入真实 ADF 并验证,读取速度极慢(虽无 MFM 错误但扇区查找困难)。放入修好的 A500+ 启动,出现校验和错误——数据写入了但不稳定。
重新优化读取算法
原读取算法对脉冲到达时间容差不足。新思路:同步 /INDEX 脉冲,记录脉冲间隔而非简单采样。利用 8 位计数器自由运行至 255,检测脉冲时读取计数值。理论最小 32(2μs),最大 128(三个连续 0)。经采样统计,主要分布在 52、89、120 附近。采用公式 value = (COUNTER - 16) / 32 截取 0~3,每 4 个值组成一个字节。利用 MFM “不允许连续两个 1”特性解码:00 无效视为 01,01→01,10→001,11→0001。实测多张磁盘 100% 成功读取,极少需重试。
写入数据 —— 尝试 5:定时器精准控制
有了可靠读取验证,分析写入偏差。写入 0x55 序列读回发现偶尔位偏移。原因有二:串口处理耗时、定时器复位方式。改为:首位在计数器 16 写入,随后每 32 计数写一位(16, 48, 80...),Timer2 8 位溢出正好对齐 8 位,实现精准 500kbps。同时压缩串口读取代码至最短。修改 Windows 端支持校验,95% 磁道一次通过,剩余 5% 重写一次即可。放入 Amiga 启动 —— 完美运行!
写入数据 —— 尝试 6:防止字节边界提前写入
用户反馈仍有校验错误。发现满字节写入后循环回始,可能在定时器溢出前提前写入首位。添加等待循环确保定时器归零后再写入首位。
写入数据 —— 尝试 7:磁道擦除预写
大量校验错误报告(XCopy Pro 显示代码 4 和 6,即扇区头和数据区校验错)。减少磁道后填充从 256 字节至 8 字节后验证大量报错,推测写入数据不足。添加 磁道擦除命令:先用 0xAA 模式全磁道写入,再写入实际数据。XCopy Pro 给出 100% 通过。
诊断模块
集成诊断命令与自检流程,帮助用户排查接线与硬件问题。
后续计划
- 项目完全开源(GPL v3),希望社区共同完善,传承 Amiga 遗产。
- Arduino UNO 写入需额外 FTDI/串口板,计划利用 23K256 SRAM 缓冲磁道数据实现 UNO 独立写入。
- 支持更多格式:ADF 仅支持 AmigaDOS 标准格式,无法处理复制保护、非标准扇区。关注 FDI 通用格式(维基百科有文档),尽可能还原原始磁道数据。
- 关注 Software Preservation Society 的 IPF 格式,但其闭源且绑定硬件销售,不予采用。
- FDI 格式无校验和,数据完整性验证需另想办法。
源代码
Arduino 固件与 Windows 应用程序源码:
GitHub 仓库
原理图
Arduino Pro Mini 接线图:

Arduino UNO 接线图:

制造工艺
- 动画演变与工艺:从幻灯片到计算机生成
- 软盘演进史:从磁存储到光存储
- 互动陀螺仪 LED 显示:NeoPixel Ring + Arduino Pro Mini
- DIY 蓝牙控制 Arduino 间谍小车
- FlickMote:基于手势的智能家居红外遥控器
- DIY Arduino TV-B-Gone:万能关机遥控器
- DIY Arduino USB 游戏手柄 — 自制高性能游戏手柄
- DIY 云朵发光服装 — LED 灯带 + Arduino Nano + SparkFun 元件
- 自制大尺寸LED主时钟带闹钟功能 — 12米外清晰可见
- Pixie:基于 Arduino Pro Mini 的 NeoPixel 智能腕表 - 极简 DIY LED 时钟
- Find Me:基于 Arduino 与蓝牙的智能寻物器制作指南
- 基于 Arduino 的 Amiga 软盘读取器:低成本开源数据恢复方案