From 511f1bc8c78db40fed6fd431126cf2643d579cb6 Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Thu, 1 Jul 2021 18:15:49 +0200 Subject: [PATCH] Experiments with WOZ writing --- cardDisk2Sequencer.go | 16 +++++++++++++--- cardDisk2SequencerDrive.go | 19 +++++++++++++++---- storage/diskette.go | 1 + storage/disketteWoz.go | 7 +++++-- storage/fileWoz.go | 27 ++++++++++++++++++++++++--- 5 files changed, 58 insertions(+), 12 deletions(-) diff --git a/cardDisk2Sequencer.go b/cardDisk2Sequencer.go index 6790759..c2e8578 100644 --- a/cardDisk2Sequencer.go +++ b/cardDisk2Sequencer.go @@ -30,7 +30,7 @@ type CardDisk2Sequencer struct { motorDelay uint64 // NE556 timer, used to delay motor off drive [2]cardDisk2SequencerDrive - lastPulse bool + lastWriteValue bool // We write transitions to the WOZ file. We store the last value to send a pulse on change. lastPulseCycles uint8 // There is a new pulse every 4ms, that's 8 cycles of 2Mhz lastCycle uint64 // 2 Mhz cycles @@ -110,8 +110,8 @@ func (c *CardDisk2Sequencer) catchUp(data uint8) { motorOn := c.step(data, true) if motorOn && currentCycle > c.lastCycle+disk2CyclestoLoseSsync { - // We have losy sync. We start the count. - //We do at least a couple 2 Mhz cycles + // We have lost sync. We start the count. + // We do at least a couple 2 Mhz cycles c.lastCycle = currentCycle - 2 } c.lastCycle++ @@ -187,6 +187,7 @@ func (c *CardDisk2Sequencer) step(data uint8, firstStep bool) bool { pulse := false c.lastPulseCycles++ if c.lastPulseCycles == disk2PulseCyles { + // Read pulse = c.drive[0].readPulse() || c.drive[1].readPulse() c.lastPulseCycles = 0 @@ -254,6 +255,15 @@ func (c *CardDisk2Sequencer) step(data uint8, firstStep bool) bool { // Load c.register = data } + + if c.q[7] && (inst&0x3) != 0 { + currentWriteValue := next >= 0x8 + writePulse := currentWriteValue != c.lastWriteValue + c.drive[0].writePulse(writePulse) + c.drive[1].writePulse(writePulse) + c.lastWriteValue = currentWriteValue + + } } //fmt.Printf("[D2SEQ] Step. seq:%x inst:%x next:%x reg:%02x\n", diff --git a/cardDisk2SequencerDrive.go b/cardDisk2SequencerDrive.go index 9939435..6cbc6cf 100644 --- a/cardDisk2SequencerDrive.go +++ b/cardDisk2SequencerDrive.go @@ -66,12 +66,15 @@ func (d *cardDisk2SequencerDrive) readPulse() bool { } // Get next bit taking into account the MC3470 latency and weak bits - var fluxBit uint8 + var fluxBit bool fluxBit, d.position, d.positionMax = d.data.GetNextBitAndPosition( d.position, d.positionMax, d.currentQuarterTrack) - d.mc3470Buffer = (d.mc3470Buffer<<1 + fluxBit) & 0x0f + d.mc3470Buffer = (d.mc3470Buffer << 1) & 0x0f + if fluxBit { + d.mc3470Buffer++ + } bit := ((d.mc3470Buffer >> 1) & 0x1) != 0 // Use the previous to last bit to add latency if d.mc3470Buffer == 0 && rand.Intn(100) < 30 { // Four consecutive zeros. It'a a fake bit. @@ -82,6 +85,14 @@ func (d *cardDisk2SequencerDrive) readPulse() bool { return bit } -func (d *cardDisk2SequencerDrive) writePulse(value uint8) { - panic("Write not implemented on woz disk implementation") +func (d *cardDisk2SequencerDrive) writePulse(value bool) { + if d.writeProtected || !d.enabled || d.data == nil { + return + } + + d.data.SetBit( + value, + d.position, + d.positionMax, + d.currentQuarterTrack) } diff --git a/storage/diskette.go b/storage/diskette.go index 3f5cb77..0ab12da 100644 --- a/storage/diskette.go +++ b/storage/diskette.go @@ -16,6 +16,7 @@ type Diskette interface { func IsDiskette(filename string) bool { data, _, err := LoadResource(filename) if err != nil { + panic(err) return false } diff --git a/storage/disketteWoz.go b/storage/disketteWoz.go index 271637b..11784d1 100644 --- a/storage/disketteWoz.go +++ b/storage/disketteWoz.go @@ -122,9 +122,12 @@ func (d *disketteWoz) Read(quarterTrack int, cycle uint64) uint8 { // TODO: avoid processing too many bits if delta is big for i := uint64(0); i < deltaBits; i++ { // Get next bit taking into account the MC3470 latency and weak bits - var fluxBit uint8 + var fluxBit bool fluxBit, d.position, d.positionMax = d.data.GetNextBitAndPosition(d.position, d.positionMax, quarterTrack) - d.mc3470Buffer = (d.mc3470Buffer<<1 + fluxBit) & 0x0f + d.mc3470Buffer = (d.mc3470Buffer << 1) & 0x0f + if fluxBit { + d.mc3470Buffer++ + } bit := (d.mc3470Buffer >> 1) & 0x1 // Use the previous to last bit to add latency if d.mc3470Buffer == 0 && rand.Intn(100) < 3 { // Four consecutive zeros. It'a a fake bit. diff --git a/storage/fileWoz.go b/storage/fileWoz.go index 3a9be55..7016116 100644 --- a/storage/fileWoz.go +++ b/storage/fileWoz.go @@ -80,7 +80,7 @@ const ( var headerWoz1 = []uint8{0x57, 0x4f, 0x5A, 0x31, 0xFF, 0x0A, 0x0D, 0x0A} var headerWoz2 = []uint8{0x57, 0x4f, 0x5A, 0x32, 0xFF, 0x0A, 0x0D, 0x0A} -func (f *FileWoz) GetNextBitAndPosition(position uint32, positionMax uint32, quarterTrack int) (uint8, uint32, uint32) { +func (f *FileWoz) GetNextBitAndPosition(position uint32, positionMax uint32, quarterTrack int) (bool, uint32, uint32) { if positionMax == 0 { // First unitialised use positionMax = ^uint32(0) // MaxUint32 @@ -93,7 +93,7 @@ func (f *FileWoz) GetNextBitAndPosition(position uint32, positionMax uint32, qua if trackIndex == 0xff { // No track defined // TODO: return random value - return 0, position, positionMax + return false, position, positionMax } trackWoz := f.tracks[trackIndex] @@ -103,7 +103,28 @@ func (f *FileWoz) GetNextBitAndPosition(position uint32, positionMax uint32, qua positionMax = trackWoz.bitCount } - return trackWoz.data[position/8] >> (7 - position%8) & 1, position, positionMax + value := (trackWoz.data[position/8] >> (7 - position%8) & 1) == 1 + return value, position, positionMax +} + +func (f *FileWoz) SetBit(value bool, position uint32, positionMax uint32, quarterTrack int) { + // The position is not moved, GetNextBitAndPosition() would have been called previously. + + trackIndex := f.trackMap[quarterTrack] + if trackIndex == 0xff { + // No track defined. Nothing is saved + return + } + trackWoz := f.tracks[trackIndex] + + mask := uint8(1) << (7 - position%8) + if value { + trackWoz.data[position/8] |= mask + } else { + trackWoz.data[position/8] &= ^mask + } + + fmt.Printf("Saving %v at %v\n", value, position) } func isFileWoz(data []uint8) bool {