Closed dirkwhoffmann closed 1 year ago
Before emulating the drive on the bit-level, some architectural changes should be made. Right now, the disk controller continuously reads byte after byte from the disk and feeds them into the FIFO buffer:
void
DiskController::serviceDiskEvent()
{
// Receive next byte from the selected drive
executeFifo();
// Schedule next event
scheduleNextDiskEvent();
}
The following image from the patent shows what happens on the real machine:
In the real disk controller, the bit stream coming from the drive is buffered in a data register 113. Whenever 16 bits have been received, the incoming word is written into the FIFO buffer. Sync word checking is done in the data register and not inside the FIFO (as implemented in vAmiga).
Next step: Emulate the data register and perform sync word checking right there.
This test case has been provided by @mras0:
I created a simple disk (read_regs_1) where track 0 is a normal amiga MFM track just shifted one bit. Note that it works fine in KS1.3 despite the data being wrong, because trackdisk.device doesn't use wordsync (it shifts the data using the blitter if necessary), try it under e.g. KS3.1 to see what I mean.
With the latest code changes, it works with KS3.1, too:
Update: hoi_1/2_converted.ext
works, too.
Next work items:
FloppyDisk
class can only handle tracks with a bit count dividable by 8. This should be made more flexible by supporting tracks with arbitrary bit counts.I would like to add that this would be a very nice feature to have (for developers) we only found out some of the timing issues when running on actual hardware with real floppies and doing a "floppy tester" to show lots of stats during the development of Eon.
For example when using a flash-drive (such as gotek) would report 0 latency (or similar at least) when doing seeking. Now I guess that makes sense as that is the case there, but that hides lots of issues when trying to get things working from actual floppies.
Another thing that we used during Eon was (in fs-uae) to set the drive to 90% speed to have some buffer due to crappy floppy disks/drives. I'm not sure if it's supported in vAmiga, but it's something that is nice to have as a dev also
I'm not sure if it's supported in vAmiga, but it's something that is nice to have as a dev also
It's not yet supported, but easy to do. Right now, the delay between the arrival times of two bytes is hard coded (it's 55.98 Agnus cycles which results in a disk rotation speed of 300rpm). This value could be altered according to some new config option.
void
DiskController::scheduleNextDiskEvent()
{
/* Advance the delay counter to achieve a disk rotation speed of 300rpm.
* Rotation speed can be measured with AmigaTestKit.adf which calculates
* the delay between consecutive index pulses. 300rpm corresponds to a
* index pulse delay of 200ms.
*/
dskEventDelay += 55.98;
DMACycle rounded = DMACycle(round(dskEventDelay));
dskEventDelay -= rounded;
if (turboMode()) {
agnus.cancel<SLOT_DSK>();
} else {
agnus.scheduleRel<SLOT_DSK>(DMA_CYCLES(rounded), DSK_ROTATE);
}
}
In the next version, there will a config option OPT_DRIVE_RPM
. It seems to work already (but needs more testing). RPM can be changed on-the-fly in RetroShell and the effect is shown by AmigaTestKit:
The implementation is pretty much straight forward:
void
DiskController::scheduleNextDiskEvent()
{
static constexpr double bytesPerTrack = 12668.0;
// How many revolutions per minute are we supposed to achieve?
FloppyDrive *drive = getSelectedDrive();
isize rpm = drive ? drive->config.rpm : 300;
// Compute the time span between two incoming bytes
double delay;
if (rpm) {
// Calculate the delay according to the desired rpm
delay = (SEC(1) * 60.0) / (double)rpm / bytesPerTrack;
} else {
// Use the value that was hard-coded in vAmiga up to version v2.2
delay = 8 * 55.98;
}
dskEventDelay += delay;
double rounded = round(dskEventDelay);
dskEventDelay -= rounded;
if (turboMode()) {
agnus.cancel<SLOT_DSK>();
} else {
agnus.scheduleRel<SLOT_DSK>(Cycle(rounded), DSK_ROTATE);
}
}
Right now, the disk controller treats the MFM bitstream as composed of bytes. As a result, the number of bits on a single track always has to be dividable by 8 and the sync words needs to be byte-aligned. This is fine for regular ADFs, but fails to work for some disks in extended ADF format.
It should be considered to make the floppy disk controller more flexible by letting it read single bits instead of bytes.