Time based disk reads

This commit is contained in:
Ivan Izaguirre 2019-12-09 20:40:00 +01:00 committed by Iván Izaguirre
parent a27ab17766
commit e14b26f876
2 changed files with 46 additions and 10 deletions

View File

@ -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

View File

@ -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