ArduinoFDC icon indicating copy to clipboard operation
ArduinoFDC copied to clipboard

Support for old FM Formats and different Sector sizes ??

Open roman65536 opened this issue 3 years ago • 11 comments

Is it possible to support also old FM Floppy drives (such as 8 inch) and different sector sizes such as 256,128 or 1024 byte, such as listed in https://en.wikipedia.org/wiki/List_of_floppy_disk_formats ? Nice feature would be, to find out what is the sector size by it self and recording method.

This way, also old IBM 8 Inch drive could be supported and also most of the CP/M formats.

rgds Roman

roman65536 avatar Dec 07 '21 10:12 roman65536

This would be awesome. I was just messing around with the code to see if I could get it to work with a Single Side Single Density 8" floppy drive I have, but the code assumes that the drive has two heads, whereas mine only has one. It properly moves the head along the disk when formatting but reports a low level disk error after attempting to write the filesystem. Also fails to read data in the low-level monitor (Drive Not Ready error). I'm not a coder so there's no way I could possibly modify this code to work on my own!

jacobtohahn avatar Jun 13 '22 00:06 jacobtohahn

A little update: With some work, I was able to interface with the 8" drive. "Drive Not Ready" error was cased by bad diskettes (the magnetic surface was being scraped off by the head) so I dug up another box which had better diskettes and after some code modification to make some of the functions only use head 1, I can (kinda) format, read, and write.

Format has issues. The first ~38 tracks read fine after the format, but after that CRC and data checksum errors begin to appear, getting more frequent the more you read. By track 60 or so pretty much all the data fails to read. However, when writing the buffer to the entire disk, you can read MUCH more, but in the late track 60s and into the 70s the drive begins to seek back and forth and some sectors have header errors. ARDUDOS format still fails to initialize the filesystem. This happens with any disk I try. Not sure if this is caused by my drive or not.

I also had to implement logic to all the write functions to drive the Low Write Current (aka TG43) line on my drive low when writing past track 43, and drive it high when writing track 43 or below. It's possible that this logic is not functioning properly, which could be causing the read issues described previously.

jacobtohahn avatar Jun 14 '22 02:06 jacobtohahn

Unfortunately the write issue for higher track numbers on 8" drives is to be expected with the current implementation and is the main reason I have not added support for such drives. The problem is that when writing to the inner (higher numbered) tracks, there is less physical space to put all the data than on outer tracks. So bits sit closer together. This becomes a problem because if bits are too close together then the changes of magnetic flux get pushed apart by each other, which means that the timing is not right when reading the data back. The solution to this is called "write precompensation" which basically slightly changes the timing while writing such that the data looks correct when reading it back.

This is not so much a problem for 5.25" and 3" drives because (I think) the disks themselves have a much higher density in the magnetic layer so can better handle flux transitions in a small space.

Now I have implemented write precompensation in a different project (see here) which supports 8" drives. It should be technically possible to port the general idea over to ArduinoFDC but that would require re-writing a significant portion of code. It was really hard getting the timing right in the other project and I'm just not up for doing that work again here, especially since only very few people would use it. It's just not worth the effort for the very small number of people who may want to write 8" disks with an Arduino. Note that reading existing disks works fine, only writing is affected by this.

dhansel avatar Jun 14 '22 03:06 dhansel

That makes sense. Unfortunate that we won’t see an implementation here, as I don’t think many others have done something similar. I’ll look around and see if someone else has done it.

jacobtohahn avatar Jun 14 '22 16:06 jacobtohahn

Now I have implemented write precompensation in a different project (see here) which supports 8" drives. It should be technically possible to port the general idea over to ArduinoFDC but that would require re-writing a significant portion of code. It was really hard getting the timing right in the other project and I'm just not up for doing that work again here, especially since only very few people would use it. It's just not worth the effort for the very small number of people who may want to write 8" disks with an Arduino. Note that reading existing disks works fine, only writing is affected by this.

Hello,

I am one in the "very small group of people" and for me, it's worth: I have recently acquired a S/23 Datamaster.

I understand the load of works of this kind of projects, I too have felt it. While you may not proceed, could you identify what sections would require modification so I could test it, please?

Both this and your ICOM project seem great! So thank you anyways for having left them open.

Regards

RetroAND avatar Feb 02 '23 12:02 RetroAND

The hard part about implementing write pre-compensation is very precise timing that it requires plus the amount of calculation necessary to know when to apply it. It's a significant change rather than a few modifications.

Other implementations (including my ICOM one) use the ATMega's SPI device to produce output at an 8 MHz rate.

First you'll have to shuffle output pins around since currently D9 is the WRITEDATA output but on the ATMega328p (Arduino Uno) D11 is the SPI output. Other supported architectures (Mega, Micro) will have different SPI pins.

The problem with using SPI on the ATMega328p is that it can't output a continuous stream of bits since it is only single-buffered. You can't queue up the next output byte while the current one is being written. You have to wait until the current SPI transfer finishes, then you can start transferring the next byte. Which means there will be a tiny gap in the data. That's fine for SPI but the data output stream to the floppy must be continuous. If there are gaps then the written data will be invalid.

There is a way around that (as I have done in the ICOM implementation): The MFM data written to the disk always has at least a one-microsecond period of "0" between two expected pulses. That one microsecond is one byte of SPI transfer. So if you time the output very precisely then you can initiate the next SPI byte (to output a pulse to the floppy at the precisely timed moment for write precomp) exactly at the right point during that microsecond gap so the pulse appears on the SPI output at the right moment. You can't use interrupts for that as the ATMega's interrupt latency is much to big - by the time the interrupt routine starts the microsecond window has already passed. So the only way to do this on the ATMega (that I know of) is to precisely count processor cycles while you're figuring out the next pulse to send and make sure that for all paths through the code it will end up doing the SPI output instruction at the correct time. That requires a lot of work counting the cycles and structuring the code accordingly. I did the work for the ICOM FDC but really don't want to do it again here.

If you want to see the differences, compare function write_data() in ArduinoFDC.cpp with write_sector_data_dd() in the ICOM firmware as well as function format_track() in ArduinoFDC.cpp and format_track_dd() in the ICOM firmware. There are a bunch of comments in there that should explain things more.

Note that the write precompensation is only necessary when writing to track 60+ on 8" floppy disks. You can read all you want without problems and you can write (at least) the first 50 tracks without any issues using ArduinoFDC.

If you want to create disks for your S/23 I suggest you use some other project (like the GreaseWeasle) that runs on faster hardware more suited to the precise timing requirements of write precomensation.

dhansel avatar Feb 02 '23 20:02 dhansel

If the microcontroller had some additional hardware to queue a second byte like a shift register such as a 74LS164 or 74LS165 directly connected to the data output while being updated by SPI clock, wouldn't that help to create a more continuous stream?

RetroAND avatar Feb 03 '23 02:02 RetroAND

Not really. What is needed is the capability to queue up a new byte for transmission while the previous one is still transmitting so the new byte can be transmitted as soon as the old one is finished. I don't see how a shift register would help with that. It needs some additional logic within the microcontroller that the ATMega just doesn't have.

dhansel avatar Feb 03 '23 03:02 dhansel

I proposed to add a shift register because it would latch the output, therefore the problem of having that undesired zero value after every SPI transmission. But as you said, the queuing is to be made before serialization, therefore a shift register per se wouldn't be that useful.

While writing this I had an idea, I need to dig in some documentation this weekend.

In any case, thank you very much.

RetroAND avatar Feb 03 '23 07:02 RetroAND

@dhansel thank you for explaining that all! I see now why this is a very difficult implementation.

@RetroAND If you make any progress or do implement this, post an update here, because I'm still interested in using it to read/write 8" disks.

jacobtohahn avatar Feb 03 '23 12:02 jacobtohahn

Bump here. I'd love to use this project for reading 5 1/4" Single Density 40 track floppies. I haven't delved into the code yet but Single density should be doable because the pulses have a low frequency and there are always clock pulses. Not sure how this project does all the capture of the pulses but i'll have a look around.

janrinze avatar Apr 29 '23 14:04 janrinze