M7: a real floppy through the Liron card
The Sony mechanism is behind the SmartPort code now. PR#5 boots ProDOS off a real 800K floppy through my board, Copy II Plus writes files to it, and a small test program gets byte-identical STATUS and READ replies from my board and from the working UniDisk, with a disk in, write-protected and with the drive empty.

A test disk my board didn’t write
Booting REF800K would only get as far as “UNABLE TO LOAD PRODOS”, and I didn’t trust that as a pass. So I built /M7TEST on the Mac and wrote it to a floppy through the working UniDisk with ADTPro. That way my board has to read a disk something else wrote.
It boots ProDOS 2.4.1, and a STARTUP program prints a sentinel line, BLOADs four 16 KB files of known content and sums each one with a small 6502 routine. DATA1-3 sit on tracks 2-6. A 1,307-block filler file pushes DATA4 out to track 72, so the boot has to seek across the disk.

For that boot the board logged 223 commands with no errors and no retries. ACK went out 4 to 6 us after /WRREQ rose, the same as with the RAM disk in M6.
The card waits as long as the drive needs
Each SmartPort call becomes a request to the mechanism code on the Pico’s second core, and the first core holds ACK low until the answer is back. The Liron card’s reply loop has no timeout, so a seek fits. Over the session:
| Count | Hold-off | |
|---|---|---|
| Commands that needed the mechanism | 109 | median 198 ms, 90 % under 595 ms, longest 844 ms |
| WRITEBLOCKs (each verified on the next revolution) | 16 | 114 to 725 ms |
| Reads served from the track buffer | the rest | about 0 ms |
The 844 ms one was a read after the motor had stopped, so it includes the spin-up. Copy II Plus copied README from the slot 6 disk onto /M7TEST with 16 WRITEBLOCKs, all good.

My board and the UniDisk give the same bytes
SPCOMPARE is a short Applesoft program on the test disk. It calls the slot 5 SmartPort entry directly and prints STATUS $00, $03 (the device info block), $05 and $01, then blocks 0-2 and block 1600 with an error code and a checksum. I ran it on both drives with the same disk in three states:
| Disk | STATUS $00 | Blocks 0-2 | Block 1600 |
|---|---|---|---|
| In, writable | F8 40 06 00 | $00, sums 56491 / 0 / 15100 | $2D bad block |
| Write-protected (window open) | FC 40 06 00 | $00, same sums | $2D |
| Drive empty | E8 40 06 00 | $2F no disk | $2F |
Every screen matched except one byte. STATUS $05 on the UniDisk ends in $FF, which is the drive ROM’s zero page $5D, and mine sent $00. I changed it, and the screens are identical now.


The block 1600 row with no disk shows the drive ROM’s order of checks. It looks for the disk first and only then at the block number, so an empty drive answers $2F even for a block that doesn’t exist. If your replacement controller returns $2D where a UniDisk returns $2F for an out-of-range block with no disk in, check the disk first. The UniDisk does.
The first run was an I/O error from my current limit
The first PR#5 came back with I/O ERROR. The board logged $27 after exactly 2000 ms, which is the motor spin-up timeout: the mechanism never reported ready. My bench supply was still set to 0.03 to 0.05 A from the host-side work, and the rail collapsed as soon as the motor started. The same dip dropped the Pico’s USB and left the level shifter reading all ones.
The mechanism needs real current. M2 measured 0.14 A on +5 and 0.13 A on +12 with the motor running, and the eject motor wants 0.5 A on +12. With the limits at 0.5 A and 1.0 A it booted on the next try.
While the rail was sagging, the card sat with REQ high and never read. My firmware took that as “please send the reply again” and re-sent the stale error about 190 times in 10 seconds. It’s capped at 5 re-sends per reply now, which is also how many times the card tries to read one.
Open threads
- This all ran on the old CN104 tap. The breakout with a heavier +5V run arrives tomorrow, and I’d like a read scan at 5.0 V on it before trusting longer runs.
- The front eject button is a plain switch wired straight to the Pico with its internal pull-up, so an unwired button reads released. The firmware turns it on from the next flash, and then it needs wiring up. Software eject already works: it’s a mechanism command over the lines the board drives.
- M8 is the daisy chain: my board in front of the working UniDisk, then behind it.