From fa7604800b8e695a6101c5206d6439cd31c4b39a Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Sun, 9 May 2021 20:09:54 +0200 Subject: [PATCH] Cleanup --- cardDisk2Sequencer.bak | 305 ------------------------------------ cardDisk2Sequencer.go | 72 ++++----- component/sn74ls174.go | 38 ----- component/sn74ls259.go | 45 ------ component/sn74ls259_test.go | 30 ---- component/sn74ls323.go | 70 --------- component/sn74ls323_test.go | 41 ----- disk/DISK2P6.rom | 65 -------- disk/main.go | 214 ------------------------- 9 files changed, 33 insertions(+), 847 deletions(-) delete mode 100644 cardDisk2Sequencer.bak delete mode 100644 component/sn74ls174.go delete mode 100644 component/sn74ls259.go delete mode 100644 component/sn74ls259_test.go delete mode 100644 component/sn74ls323.go delete mode 100644 component/sn74ls323_test.go delete mode 100644 disk/DISK2P6.rom delete mode 100644 disk/main.go diff --git a/cardDisk2Sequencer.bak b/cardDisk2Sequencer.bak deleted file mode 100644 index 56b9187..0000000 --- a/cardDisk2Sequencer.bak +++ /dev/null @@ -1,305 +0,0 @@ -package izapple2 - -import ( - "fmt" - - "github.com/ivanizag/izapple2/component" - "github.com/ivanizag/izapple2/storage" -) - -// TODO: fast mode - -/* -See: - "Understanding the Apple II, chapter 9" - Beneath Apple ProDOS, Appendix - Phases: http://yesterbits.com/media/pubs/AppleOrchard/articles/disk-ii-part-1-1983-apr.pdf - IMW Floppy Disk I/O Controller info: (https://www.brutaldeluxe.fr/documentation/iwm/apple2_IWM_INFO_19840510.pdf) - Woz https://applesaucefdc.com/woz/reference2/ - Schematic: https://mirrors.apple2.org.za/ftp.apple.asimov.net/documentation/hardware/schematics/APPLE_DiskII_SCH.pdf - - -*/ - -// CardDisk2Sequencer is a DiskII interface card -type CardDisk2Sequencer struct { - cardBase - - p6ROM []uint8 - latch component.SN74LS259 // 8-bit latch - register component.SN74LS323 // 8-bit shift/storage register - flipFlop component.SN74LS174 // hex flip-flop - motorDelay uint8 // NE556 timer, used to delay motor off - drive [2]cardDisk2SequencerDrive - - lastPulse bool - lastPulseCycles uint8 // There is a new pulse every 4ms, that's 8 cycles of 2Mhz - - lastCycle uint64 // 2 Mhz cycles -} - -const disk2MotorOffDelay = uint8(20) // 2 Mhz cycles, TODO: how long? -const disk2PulseCcyles = uint8(8) // 8 cycles = 4ms * 2Mhz - -// NewCardDisk2Sequencer creates a new CardDisk2Sequencer -func NewCardDisk2Sequencer() *CardDisk2Sequencer { - var c CardDisk2Sequencer - c.name = "Disk II" - c.loadRomFromResource("/DISK2.rom") - - data, _, err := storage.LoadResource("/DISK2P6raw.rom") - if err != nil { - // The resource should be internal and never fail - panic(err) - } - c.p6ROM = data - - return &c -} - -func (c *CardDisk2Sequencer) dumpState() { - fmt.Printf("Q5 %v, Q4 %v, delay %v\n", c.latch.Q(5), c.latch.Q(4), c.motorDelay) -} - -// GetInfo returns card info -func (c *CardDisk2Sequencer) GetInfo() map[string]string { - info := make(map[string]string) - info["rom"] = "16 sector" - // TODO: add drives info - return info -} - -func (c *CardDisk2Sequencer) reset() { - // UtA2e 9-12, all switches forced to off - c.latch.Reset() -} - -func (c *CardDisk2Sequencer) assign(a *Apple2, slot int) { - c.addCardSoftSwitches(func(_ *ioC0Page, address uint8, data uint8, write bool) uint8 { - /* - Slot card pins to SN74LS259 mapping: - slot_address[3,2,1] => latch_address[2,1,0] - slot_address[0] => latch_data - slot_dev_selct => latch_write_enable // It will be true - */ - c.latch.Write(address>>1, (address&1) != 0, true) - - // Advance the Disk2 state machine since the last call to softswitches - c.catchUp(data) - //c.dumpState() - /* - Slot card pins to SN74LS259 mapping: - slot_address[0] => latch_oe2_n - */ - register_output_enable_neg := (address & 1) != 0 - if !register_output_enable_neg { - reg := c.register.Output() - return component.ReversePins(reg) - } else { - return 33 - } - }, "DISK2SEQ") - - c.cardBase.assign(a, slot) -} - -func (c *CardDisk2Sequencer) catchUp(data uint8) { - currentCycle := c.a.cpu.GetCycles() << 1 // Disk2 cycles are x2 cpu cycle - - motorOn := c.step(data, true) - if motorOn && c.lastCycle == 0 { - // The motor was off, now on. We start the count. We do at least a couple 2 Mhz cycles - c.lastCycle = currentCycle - 2 - } - c.lastCycle++ - - for motorOn && c.lastCycle <= currentCycle { - motorOn = c.step(data, false) - c.lastCycle++ - } - - if !motorOn { - c.lastCycle = 0 // No tracking done - } -} - -func (c *CardDisk2Sequencer) step(data uint8, firstStep bool) bool { - /* - Q4 and Q6 set on the sofswitches is stored on the - latch. - */ - q5 := c.latch.Q(5) // Drive selection - q4 := c.latch.Q(4) // Motor on (before delay) - - /* - Motor On comes from the latched q4 via the 556 to - provide a delay. The delay is reset while q4 is on. - */ - if q4 { - c.motorDelay = disk2MotorOffDelay - } - motorOn := c.motorDelay > 0 - - /* - The pins for the cable drives ENBL1 and ENBL2 are - connected to q5 and motor using half of the 74LS132 - NAND to combine them. - */ - c.drive[0].enable(!q5 && motorOn) - c.drive[1].enable(q5 && motorOn) - - /* - Motor on AND the 2 Mhz clock (Q3 pin 37 of the slot) - are connected to the clok pulse of the shift register - if off, the sequences does not advance. The and uses - another quarter of the 74LS132 NAND. - */ - if !motorOn { - c.flipFlop.Reset() - return false - } - c.motorDelay-- - - /* - The register is not connected to the data bus directly. - The pin correspondence is: - - - - - /* - Head movements. We assume it's instantaneous on Q0-Q3 change. We - will place it on the first step. - Q0 to Q3 are connected directly to the drives. - */ - if firstStep { - q0 := c.latch.Q(0) - q1 := c.latch.Q(1) - q2 := c.latch.Q(3) - q3 := c.latch.Q(3) - c.drive[0].moveHead(q0, q1, q2, q3) - c.drive[1].moveHead(q0, q1, q2, q3) - } - - /* - The reading from the drive is converted to a pulse detecting - changes using Q3 and Q4 of the flip flop, combines with - the last quarter of the 74LS132 NAND. - The woz format provides the pulse directly and we wont emulate - this detection. - */ - pulse := false - c.lastPulseCycles++ - if c.lastPulseCycles == disk2PulseCcyles { - pulse = c.drive[0].readPulse() || - c.drive[1].readPulse() - c.lastPulseCycles = 0 - } - - /* The write protected signal comes directly from the any of the - drives being enabled (motor on) and write protected. - */ - wProt := (c.drive[0].enabled && c.drive[0].writeProtected) || - (c.drive[1].enabled && c.drive[1].writeProtected) - - /* - The next instruction for the sequencer is retrieved from - the ROM P6 using the address: - A0, A5, A6, A7 <= sequence from 74LS174 - A1 =< MSB of register (pin Q7) - A2 <= Q6 from 9334 - A3 <= Q7 from 9334 - A4 <= pulse transition - */ - romAddress := component.PinsToByte([8]bool{ - c.flipFlop.Q(5), // seq1 - c.register.Q7(), - c.latch.Q(6), - c.latch.Q(7), - pulse, - c.flipFlop.Q(2), // seq0 - c.flipFlop.Q(1), // seq2 - c.flipFlop.Q(0), //seq3 - }) - - sequence := component.PinsToByte([8]bool{ - c.flipFlop.Q(0), - c.flipFlop.Q(1), - c.flipFlop.Q(5), - c.flipFlop.Q(2), - }) - - fmt.Printf("For Q6(%v) Q7(%v) H(%v) P(%v) Seq(%x) => ", - c.latch.Q(6), c.latch.Q(6), c.register.Q7(), pulse, sequence, - ) - - romDataByte := c.p6ROM[romAddress] - romData := component.ByteToPins(romDataByte) - - inst := component.PinsToByte([8]bool{ - romData[0], - romData[1], - romData[2], - romData[3], - }) - - next := component.PinsToByte([8]bool{ - romData[7], - romData[6], - romData[5], - romData[4], - }) - fmt.Printf("cmd(%x) seq(%x)\n", inst, next) - - /* - The next sequence is feed back to the flip-flops. - Notes: Q3 and Q4 are not used as we are not emulating - the pulse detection. MotorOn here is always true, the - code for motorOn false is above. - */ - c.flipFlop.Update( - romData[7], - romData[6], - romData[4], - false, - false, - romData[5], - motorOn, - ) - - /* - sequenceNew := component.PinsToByte([8]bool{ - c.flipFlop.Q(2), - c.flipFlop.Q(5), - c.flipFlop.Q(1), - c.flipFlop.Q(0), - }) - */ - - /* - The pins for the register shifter update are: - SR(CLR) <- ROM D3 - S1 <- ROM D0 - S0 <- ROM D1 - DS0(SR) <- WPROT pin of the selected drive - DS7(SL) <- ROM D2 - IO[7.0] <-> D[0-7] slot data bus (the order is reversed) - - */ - c.register.Update( - component.ReversePins(data), - romData[1], // S0 - romData[0], // S1 - romData[3], // SR_N - wProt, // DS0 - romData[2], // DS1 - ) - - /* - fmt.Printf("Seq %x. pulse %v, P6ROM[%02x]=%02x -> %x-%x, reg %02x\n", - sequence, pulse, romAddress, romDataByte, - sequenceNew, command, - component.ReversePins(c.register.Output())) - */ - return true -} diff --git a/cardDisk2Sequencer.go b/cardDisk2Sequencer.go index e2f2106..98e1400 100644 --- a/cardDisk2Sequencer.go +++ b/cardDisk2Sequencer.go @@ -1,8 +1,6 @@ package izapple2 import ( - "fmt" - "github.com/ivanizag/izapple2/component" "github.com/ivanizag/izapple2/storage" ) @@ -26,10 +24,10 @@ type CardDisk2Sequencer struct { cardBase p6ROM []uint8 - latch component.SN74LS259 // 8-bit latch - register uint8 // 8-bit shift/storage register SN74LS323 - sequence uint8 // 4 bits stored in an hex flip-flop SN74LS174 - motorDelay uint8 // NE556 timer, used to delay motor off + q [8]bool // 8-bit latch SN74LS259 + register uint8 // 8-bit shift/storage register SN74LS323 + sequence uint8 // 4 bits stored in an hex flip-flop SN74LS174 + motorDelay uint8 // NE556 timer, used to delay motor off drive [2]cardDisk2SequencerDrive lastPulse bool @@ -38,8 +36,17 @@ type CardDisk2Sequencer struct { lastCycle uint64 // 2 Mhz cycles } -const disk2MotorOffDelay = uint8(20) // 2 Mhz cycles, TODO: how long? -const disk2PulseCcyles = uint8(8) // 8 cycles = 4ms * 2Mhz +const ( + disk2MotorOffDelay = uint8(20) // 2 Mhz cycles, TODO: how long? + disk2PulseCcyles = uint8(8) // 8 cycles = 4ms * 2Mhz + + /* + We skip register calculations for long periods with the motor + on but not reading bytes. It's an optimizations, 10000 is too + short for cross track sync copy protections. + */ + disk2CyclestoLoseSsync = 100000 +) // NewCardDisk2Sequencer creates a new CardDisk2Sequencer func NewCardDisk2Sequencer() *CardDisk2Sequencer { @@ -57,10 +64,6 @@ func NewCardDisk2Sequencer() *CardDisk2Sequencer { return &c } -func (c *CardDisk2Sequencer) dumpState() { - fmt.Printf("Q5 %v, Q4 %v, delay %v\n", c.latch.Q(5), c.latch.Q(4), c.motorDelay) -} - // GetInfo returns card info func (c *CardDisk2Sequencer) GetInfo() map[string]string { info := make(map[string]string) @@ -71,34 +74,30 @@ func (c *CardDisk2Sequencer) GetInfo() map[string]string { func (c *CardDisk2Sequencer) reset() { // UtA2e 9-12, all switches forced to off - c.latch.Reset() + c.q = [8]bool{} } func (c *CardDisk2Sequencer) assign(a *Apple2, slot int) { c.addCardSoftSwitches(func(_ *ioC0Page, address uint8, data uint8, write bool) uint8 { /* - Slot card pins to SN74LS259 mapping: + Slot card pins to SN74LS259 latch mapping: slot_address[3,2,1] => latch_address[2,1,0] slot_address[0] => latch_data - slot_dev_selct => latch_write_enable // It will be true + slot_dev_selct => latch_write_enable ;It will be true */ - c.latch.Write(address>>1, (address&1) != 0, true) + c.q[address>>1] = (address & 1) != 0 // Advance the Disk2 state machine since the last call to softswitches c.catchUp(data) - //c.dumpState() /* Slot card pins to SN74LS259 mapping: slot_address[0] => latch_oe2_n */ register_output_enable_neg := (address & 1) != 0 if !register_output_enable_neg { - //if c.register >= 0x80 && address == 0xc { - // fmt.Printf("Byte %x\n", c.register) - //} return c.register } else { - return 33 + return 33 // Floating } }, "DISK2SEQ") @@ -109,9 +108,9 @@ func (c *CardDisk2Sequencer) catchUp(data uint8) { currentCycle := c.a.cpu.GetCycles() << 1 // Disk2 cycles are x2 cpu cycle motorOn := c.step(data, true) - //if motorOn && c.lastCycle == 0 { - if motorOn && currentCycle > c.lastCycle+100000 { // With 10000, cross track snc not working - // The motor was off, now on. We start the count. We do at least a couple 2 Mhz cycles + if motorOn && currentCycle > c.lastCycle+disk2CyclestoLoseSsync { + // We have losy sync. We start the count. + //We do at least a couple 2 Mhz cycles c.lastCycle = currentCycle - 2 } c.lastCycle++ @@ -122,7 +121,7 @@ func (c *CardDisk2Sequencer) catchUp(data uint8) { } if !motorOn { - c.lastCycle = 0 // No tracking done + c.lastCycle = 0 // Sync lost } } @@ -131,8 +130,8 @@ func (c *CardDisk2Sequencer) step(data uint8, firstStep bool) bool { Q4 and Q6 set on the sofswitches is stored on the latch. */ - q5 := c.latch.Q(5) // Drive selection - q4 := c.latch.Q(4) // Motor on (before delay) + q5 := c.q[5] // Drive selection + q4 := c.q[4] // Motor on (before delay) /* Motor On comes from the latched q4 via the 556 to @@ -169,10 +168,10 @@ func (c *CardDisk2Sequencer) step(data uint8, firstStep bool) bool { Q0 to Q3 are connected directly to the drives. */ if firstStep { - q0 := c.latch.Q(0) - q1 := c.latch.Q(1) - q2 := c.latch.Q(2) - q3 := c.latch.Q(3) + q0 := c.q[0] + q1 := c.q[1] + q2 := c.q[2] + q3 := c.q[3] c.drive[0].moveHead(q0, q1, q2, q3) c.drive[1].moveHead(q0, q1, q2, q3) } @@ -214,21 +213,17 @@ func (c *CardDisk2Sequencer) step(data uint8, firstStep bool) bool { romAddress := component.PinsToByte([8]bool{ seqBits[1], // seq1 high, - c.latch.Q(6), - c.latch.Q(7), + c.q[6], + c.q[7], !pulse, seqBits[0], // seq0 seqBits[2], // seq2 - seqBits[3], //seq3 + seqBits[3], // seq3 }) - //fmt.Printf("For Q6(%v) Q7(%v) H(%v) P(%v) Seq(%x) => ", - // c.latch.Q(6), c.latch.Q(6), high, pulse, c.sequence) - romData := c.p6ROM[romAddress] inst := romData & 0xf next := romData >> 4 - //fmt.Printf("cmd(%x) seq(%x) ", inst, next) /* The pins for the register shifter update are: @@ -262,6 +257,5 @@ func (c *CardDisk2Sequencer) step(data uint8, firstStep bool) bool { } c.sequence = next - //fmt.Printf("reg %02x\n", c.register) return true } diff --git a/component/sn74ls174.go b/component/sn74ls174.go deleted file mode 100644 index 42a15a2..0000000 --- a/component/sn74ls174.go +++ /dev/null @@ -1,38 +0,0 @@ -package component - -/* - SN74LS174: hex D flip-flop - - http://www.skot9000.com/ttl/datasheets/174.pdf - -Pins: - A0, A1, A2: Address inputs. 'address' parameter of Write() - D: Data input. 'value' parameter of Write() - E: Enable input. 'enable' parameter of Write() - C: Clear input. Method Reset() - Q0, Q7: Parallel latch outputs. Return of Q(n) -*/ - -type SN74LS174 struct { - q [6]bool -} - -func (o *SN74LS174) Update(d0, d1, d2, d3, d4, d5, mr bool) { - o.q[0] = d0 && mr - o.q[1] = d1 && mr - o.q[2] = d2 && mr - o.q[3] = d3 && mr - o.q[4] = d4 && mr - o.q[5] = d5 && mr -} - -func (o *SN74LS174) Reset() { - o.Update(false, false, false, false, false, false, false) -} - -func (o *SN74LS174) Q(index uint8) bool { - if index > 5 { - panic("There are only 6 flip flops") - } - return o.q[index] -} diff --git a/component/sn74ls259.go b/component/sn74ls259.go deleted file mode 100644 index 8d09ba0..0000000 --- a/component/sn74ls259.go +++ /dev/null @@ -1,45 +0,0 @@ -package component - -/* - SN74LS259 or 9344: 8-bit addressable latch - - http://www.skot9000.com/ttl/datasheets/259.pdf - -Pins: - A0, A1, A2: Address inputs. 'address' parameter of Write() - D: Data input. 'value' parameter of Write() - E: Enable input. 'enable' parameter of Write() - C: Clear input. Method Reset() - Q0, Q7: Parallel latch outputs. Return of Q(n) -*/ - -type SN74LS259 struct { - value uint8 -} - -func (o *SN74LS259) Write(address uint8, value bool, enable bool) { - if address > 7 { - panic("The address can have only three bits") - } - - if !enable { - return - } - - o.value = o.value &^ (uint8(1) << address) - if value { - o.value |= 1 << address - } -} - -func (o *SN74LS259) Q(address uint8) bool { - if address > 7 { - panic("The address can have only three bits") - } - - return ((o.value >> address) & 1) == 1 -} - -func (o *SN74LS259) Reset() { - o.value = 0 -} diff --git a/component/sn74ls259_test.go b/component/sn74ls259_test.go deleted file mode 100644 index 1ffd5d9..0000000 --- a/component/sn74ls259_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package component - -import ( - "testing" -) - -func TestSN74LS259WriteTrue(t *testing.T) { - var o SN74LS259 - o.Write(2, true, true) - if !o.Q(2) { - t.Error("Wrote true but got false") - } -} - -func TestSN74LS259WriteFalse(t *testing.T) { - var o SN74LS259 - o.Write(1, false, true) - if o.Q(1) { - t.Error("Wrote false but got true") - } -} - -func TestSN74LS259WriteTrueThenFalse(t *testing.T) { - var o SN74LS259 - o.Write(5, true, true) - o.Write(5, false, true) - if o.Q(5) { - t.Error("Wrote true the false but got true") - } -} diff --git a/component/sn74ls323.go b/component/sn74ls323.go deleted file mode 100644 index d3b0ffe..0000000 --- a/component/sn74ls323.go +++ /dev/null @@ -1,70 +0,0 @@ -package component - -/* - SN74LS323: 8-bit shift storage register - - http://www.skot9000.com/ttl/datasheets/323.pdf - -Pins: - CP: Clock pulse. Call to Update() - DS0: Serial data input for shift right. 'ds0' parameter of Update() - DS7: Serial data input for shift left. 'ds1' parameter of Update() - I0-7: Parallel data input. 'data' parameter of Update() - O0-7: Parallel data output. Return of Output() - OE1-2: Not supported - Q0: Serial outputs LSB. Return of Q0() - Q7: Serial outputs MSB. Return of Q7() - S0: Mode select, 's0' parameter of Update() - S1: Mode select, 's1' parameter of Update() - SR: Sync reset (active low), 'sr_n' parameter of Update() - -Note: left for datasheet (I0-I1-I2..I7) is right for uint8 (b7-b6...b0) -*/ - -type SN74LS323 struct { - value uint8 -} - -func (o *SN74LS323) Update(data uint8, s0 bool, s1 bool, sr_n bool, ds0 bool, ds7 bool) { - if !sr_n { - // Reset on SR low - o.value = 0 - return - } - - if s1 { - if s0 { - // high, high: Parallel load - o.value = data - } else { - // high, low: Shift left (it's shift right for uint8) - o.value >>= 1 - if ds7 { - o.value += 0x80 - } - } - } else { - if s0 { - // low, high: Shift right (it's shift left for uint8) - o.value <<= 1 - if ds0 { - o.value += 0x01 - } - } else { - // low, low: Hold - // do nothing - } - } -} - -func (o *SN74LS323) Q0() bool { - return (o.value & 1) != 0 -} - -func (o *SN74LS323) Q7() bool { - return (o.value & 0x80) != 0 -} - -func (o *SN74LS323) Output() uint8 { - return o.value -} diff --git a/component/sn74ls323_test.go b/component/sn74ls323_test.go deleted file mode 100644 index 69e24dc..0000000 --- a/component/sn74ls323_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package component - -import ( - "testing" -) - -func TestSN74LS323Reset(t *testing.T) { - var o SN74LS323 - o.value = 0x89 - o.Update(0x12, false, false, false, false, false) - if o.Output() != 0 { - t.Error("Value should reset to 0") - } -} - -func TestSN74LS323ShiftLeft(t *testing.T) { - var o SN74LS323 - o.value = 0x11 - o.Update(0x12, false, true, true, false, true) - if o.Output() != 0x88 { - t.Error("Bad shift left") - } -} - -func TestSN74LS323ShiftRight(t *testing.T) { - var o SN74LS323 - o.value = 0x11 - o.Update(0x12, true, false, true, true, false) - if o.Output() != 0x23 { - t.Error("Bad shift right") - } -} - -func TestSN74LS323Load(t *testing.T) { - var o SN74LS323 - o.value = 0x11 - o.Update(0x12, true, true, true, true, false) - if o.Output() != 0x12 { - t.Error("Bad load") - } -} diff --git a/disk/DISK2P6.rom b/disk/DISK2P6.rom deleted file mode 100644 index 6d79ce1..0000000 --- a/disk/DISK2P6.rom +++ /dev/null @@ -1,65 +0,0 @@ -� - - - -99;;8( - - - -99;;-�8H - - - -(H(H(H(H-H8H - - - -(H(H(H(H���� - - - -XxXxXxXxXxXx - - - -XxXxXxXx���� - - - -hh�hh�h�h� - - - -hh�hh����� - - - -������������ - - - -������������ - - - -�ȨȨȨ�)Y�� - - - -�ȨȨȨ����� - - - -������������ - - - -������������ - - - -����M�� - - - -���� \ No newline at end of file diff --git a/disk/main.go b/disk/main.go deleted file mode 100644 index 8a58794..0000000 --- a/disk/main.go +++ /dev/null @@ -1,214 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/ivanizag/izapple2/component" - "github.com/ivanizag/izapple2/storage" -) - -// https://embeddedmicro.weebly.com/apple-ii-p6-prom-dump.html -func getInstruction(data []uint8, Q6 bool, Q7 bool, high bool, pulse bool, sequence uint8) uint8 { - - seqBits := component.ByteToPins(sequence) - address := component.PinsToByte([8]bool{ - seqBits[1], - high, - Q6, - Q7, - !pulse, - seqBits[0], - seqBits[2], - seqBits[3], - }) - v := data[address] - //fmt.Printf("Seq %x. pulse %v, P6ROM[%02x]=%02x", sequence, pulse, i, v) - - fmt.Printf("For Q6(%v) Q7(%v) H(%v) P(%v) Seq(%x) => ", - Q6, Q7, high, pulse, sequence, - ) - - return v -} - -func printTable(data []uint8, q6 bool, q7 bool) { - for i := uint8(0); i < 16; i++ { - fmt.Printf("%x %02x %02x %02x %02x\n", - i, - getInstruction(data, q6, q7, false, true, i), - getInstruction(data, q6, q7, false, false, i), - getInstruction(data, q6, q7, true, true, i), - getInstruction(data, q6, q7, true, false, i), - ) - } -} - -func mainXX() { - fmt.Println("SM Analysis:") - data, _, _ := storage.LoadResource("/DISK2P6.rom") - - fmt.Println("Q6 On, Q7 Off") - printTable(data, true, false) - fmt.Println("Q6 Off, Q7 Off") - printTable(data, false, false) - fmt.Println("Q6 On, Q7 On") - printTable(data, true, true) - fmt.Println("Q6 Off, Q7 On") - printTable(data, false, true) - -} - -type lsq struct { - sequence uint8 - register uint8 // 74LS323, https://components101.com/asset/sites/default/files/component_datasheet/SN74LS323-Datasheet.pdf -} - -func main() { - /* - $C08E -> q7 false - Every time $C08C high byte is set -> q6 false - */ - data, _, _ := storage.LoadResource("/DISK2P6.rom") - - wozData, _, err := storage.LoadResource("/home/casa/applerelease/disks/woz test images/WOZ 2.0/DOS 3.3 System Master.woz") - if err != nil { - panic("Error creando woz") - } - woz, err := storage.NewFileWoz(wozData) - - var lsq lsq - - nibs := woz.DumpTrackAsNib(0) - for i := 0; i < 20; i++ { - fmt.Printf("\n%v: ", i) - for j := 0; j < 16; j++ { - fmt.Printf("%02x ", nibs[i*16+j]) - } - } - fmt.Println("") - - /* - bits := woz.DumpTrackAsWoz(0) - for i := 0; i < 20; i++ { - fmt.Printf("%v: %02x\n", i, bits[i]) - } - */ - - position := uint32(1) - maxPosition := uint32(50304) - hcycles := 0 - lastReadCycle := 0 - bit := uint8(0) - for position != 0 { - hcycles++ - pulse := false - if (hcycles % 8) == 0 { - bit, position, maxPosition = woz.GetNextBitAndPosition(position, maxPosition, 0) - pulse = bit != 0 - fmt.Printf("==Read bit %v @ %v \n", bit, position) - } - high := (lsq.register & 0x80) != 0 - command := getInstruction(data, false, false, high, pulse, lsq.sequence) - //fmt.Printf(" reg %02x\n", lsq.register) - inst := command & 0xf - next := command >> 4 - fmt.Printf("cmd(%x) seq(%x)\n", inst, next) - - /* - - https://www.youtube.com/watch?v=r1VlrJboDMw 21:30 - - - 74LS323 pins: (register) - SR = inst[3] - S1 = inst[0] - S0 = inst[1] - DS0 = write protect - DS7 = inst[2] - IO[7.0] = D[7-0] slot data bus - OE1 = AD[0], register copied to bus depending on this - OE2 = (DEV pin 41 slot) - Q7 = high - Q0 = not used - CP = clock pulse (Q3 pin37 slot, 2Mhz clock) AND motor (using 74LS132) - - ROM P6 pins: - A0, A5, A6, A7 <= sequence from 74LS174 - D4, D5, D6, D7 => sequence to 74LS174 - A4 <= pulse transition - A2 <= Q6 from 9334 - A3 <= Q7 from 9334 - A1 =< MSB of register (pin Q7) - D0-S3 => S1, S0, SR and DS7 of register - E2: motor - - 74LS174 pins (hex flip flop) (sequence 0,1,2,5) - CP = clock pulse (Q3 pin37 slot, 2Mhz clock) AND motor (using 74LS132) - MR = motor - seq: - D0 <- ROM D7 - Q0 -> ROM A7 - D1 <- ROM D6 - Q1 -> ROM A6 - D2 <- ROM D4 - Q2 -> ROM A5 - D5 <- ROM D5 - Q5 -> ROM A0 - pulse transition: - D3 <- from Q4 - Q3 -> and not Q4 -> to ROM A4 (detects change in pulse) - D4 <- pulse (from disk) - Q4 -> to D3 - - 9334 (or 74LS259) 8 bit latch - Q0-Q3: phases - Q4: motor control to 556 - Q5: drive select - Q6: to ROM P6 - Q7: to ROM P7 - R: to slot reset - A0: slot AD[1] - A1: slot AD[2] - A3: slot AD[3] - D: slot AD[0] - E: (DEV 41 pin slot) - - - Write on Q7 from the 9334 and Q0 (seq[3]) transition on 74ls174 - - 556, for the motor signal, to continue a bit longer? - - */ - - //fmt.Printf("cmd %02x, reg %02x, inst %x, seq %x, next %x, pulse %v ", command, lsq.register, inst, lsq.sequence, next, pulse) - switch inst { - case 0: // CLR, 74LS323 pin 9, Sync Reset - lsq.register = 0 - //fmt.Printf("CLR") - case 8: // NOP - // Nothing - //fmt.Printf("NOP") - case 9: // SL0 -> S1=1, S0=0 - lsq.register = lsq.register << 1 - //fmt.Printf("SL0") - case 0xa: // SR - lsq.register = lsq.register >> 1 // + write protect MSB on pin 11 DS0 - //fmt.Printf("SR") - case 0xb: // LD -> parallel load S1=1, S0=1 - panic("not in read mode") - // lsq.register = bus - case 0xd: // SL1 - lsq.register = 1 + (lsq.register << 1) - //fmt.Printf("SL1") - default: - panic("missing instruction") - } - lsq.sequence = next - //fmt.Println("") - if lsq.register > 0x7f && (hcycles-lastReadCycle) > 60 { - fmt.Printf("Byte %02x at %v\n", lsq.register, position) - lastReadCycle = hcycles - } - } - -}