From e14b26f8763747f535ae4c9da5701f692a84b340 Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Mon, 9 Dec 2019 20:40:00 +0100 Subject: [PATCH] Time based disk reads --- cardDisk2.go | 9 ++++++--- diskette16sector.go | 47 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/cardDisk2.go b/cardDisk2.go index ccd217d..d2e8555 100644 --- a/cardDisk2.go +++ b/cardDisk2.go @@ -126,13 +126,16 @@ func (c *cardDisk2) assign(a *Apple2, slot int) { c.cardBase.assign(a, slot) } +// Q6: shift/load +// Q7: read/write + func (c *cardDisk2) softSwitchQ6Q7(index uint8, in uint8) uint8 { switch index { case 0xC: // Q6L c.q6 = false case 0xD: // Q6H c.q6 = true - case 0xE: // Q/L + case 0xE: // Q7L c.q7 = false case 0xF: // Q7H c.q7 = true @@ -151,13 +154,13 @@ func (c *cardDisk2) processQ6Q7(in uint8) { if d.diskette == nil { return } - if !c.q6 { + if !c.q6 { // shift if !c.q7 { // Q6L-Q7L: Read c.dataLatch = d.diskette.read(d.tracksStep, c.a.cpu.GetCycles()) } else { // Q6L-Q7H: Write the dataLatch value to disk. Shift data out d.diskette.write(d.tracksStep, c.dataLatch, c.a.cpu.GetCycles()) } - } else { + } else { // load if !c.q7 { // Q6H-Q7L: Sense write protect / prewrite state // Bit 7 of the control status register means write protected c.dataLatch = 0 // Never write protected diff --git a/diskette16sector.go b/diskette16sector.go index 9c8e60d..9eb50c8 100644 --- a/diskette16sector.go +++ b/diskette16sector.go @@ -20,28 +20,58 @@ const ( nibImageSize = numberOfTracks * nibBytesPerTrack dskImageSize = numberOfTracks * numberOfSectors * bytesPerSector defaultVolumeTag = 254 + cyclesPerBit = 4 ) type diskette16sector struct { - track [numberOfTracks][]byte - position int + track [numberOfTracks][]byte + timeBased bool + // Not time based implementation + position int // For not time based implemenation + // Time based implementation, expermiental + cycleOn uint64 // Cycle when the disk was last turned on } -func (d *diskette16sector) powerOn(_ uint64) { - // Not needed +func (d *diskette16sector) powerOn(cycle uint64) { + d.cycleOn = cycle } func (d *diskette16sector) powerOff(_ uint64) { // Not needed } -func (d *diskette16sector) read(quarterTrack int, _ uint64) uint8 { - track := quarterTrack / stepsPerTrack - value := d.track[track][d.position] +func (d *diskette16sector) getBitPositionInTrack(cycle uint64) int { + // Calculate how long the disk has been spinning. We move one bit every 4 cycles. + // In this implementation we don't take into account hot long the motor takes to be at full speed. + cycles := cycle - d.cycleOn + position := cycles / cyclesPerBit + return int(position % (8 * nibBytesPerTrack)) // Ignore full turns +} + +func (d *diskette16sector) read(quarterTrack int, cycle uint64) uint8 { + track := d.track[quarterTrack/stepsPerTrack] + if d.timeBased { + bitPosition := d.getBitPositionInTrack(cycle) + bytePosition := bitPosition / 8 + shift := uint(bitPosition % 8) + if shift == 1 { + // We continue having the previous data for a little longer + shift = 0 + } + value := track[bytePosition] + value >>= shift + //fmt.Printf("%v, %v, %v, %x\n", bitPosition, shift, bytePosition, uint8(data)) + return value + } + value := track[d.position] d.position = (d.position + 1) % nibBytesPerTrack + //fmt.Printf("%v, %v, %v, %x\n", 0, 0, d.position, uint8(value)) return value } func (d *diskette16sector) write(quarterTrack int, value uint8, _ uint64) { + if d.timeBased { + panic("Write not implmented on time based disk implementation") + } track := quarterTrack / stepsPerTrack d.track[track][d.position] = value d.position = (d.position + 1) % nibBytesPerTrack @@ -50,6 +80,9 @@ func (d *diskette16sector) write(quarterTrack int, value uint8, _ uint64) { func loadDisquette(filename string) (*diskette16sector, error) { var d diskette16sector + // Experimental + d.timeBased = true + data, err := loadResource(filename) if err != nil { return nil, err