Fixed stepper magnet handling for disks

This commit is contained in:
Jorj Bauer 2017-12-28 22:49:20 -05:00
parent ce41acf784
commit 4545258bc4
2 changed files with 69 additions and 52 deletions

View File

@ -23,7 +23,12 @@ DiskII::DiskII(AppleMMU *mmu)
this->mmu = mmu; this->mmu = mmu;
curTrack = 0; trackPos[0] = trackPos[1] = 0;
prevTrack[0] = prevTrack[1] = 0;
stepperPhases[0] = stepperPhases[1] = 0;
curPhase[0] = curPhase[1] = 0;
curTrack[0] = curTrack[1] = 0;
trackDirty = false; trackDirty = false;
trackToRead = -1; trackToRead = -1;
trackToFlush = -1; trackToFlush = -1;
@ -46,8 +51,15 @@ DiskII::~DiskII()
void DiskII::Reset() void DiskII::Reset()
{ {
curTrack = 0; trackPos[0] = trackPos[1] = 0;
prevTrack[0] = prevTrack[1] = 0;
stepperPhases[0] = stepperPhases[1] = 0;
curPhase[0] = curPhase[1] = 0;
curTrack[0] = curTrack[1] = 0;
trackDirty = false; trackDirty = false;
trackToRead = -1;
trackToFlush = -1;
writeMode = false; writeMode = false;
writeProt = false; // FIXME: expose an interface to this writeProt = false; // FIXME: expose an interface to this
@ -83,7 +95,7 @@ uint8_t DiskII::readSwitches(uint8_t s)
case 0x08: // drive off case 0x08: // drive off
indicatorIsOn[selectedDisk] = 99; indicatorIsOn[selectedDisk] = 99;
g_display->setDriveIndicator(selectedDisk, false); // FIXME: after a spell... g_display->setDriveIndicator(selectedDisk, false); // FIXME: after a spell...
checkFlush(curTrack); checkFlush(curTrack[selectedDisk]);
break; break;
case 0x09: // drive on case 0x09: // drive on
indicatorIsOn[selectedDisk] = 100; indicatorIsOn[selectedDisk] = 100;
@ -194,54 +206,54 @@ void DiskII::writeSwitches(uint8_t s, uint8_t v)
} }
} }
// where phase is the address poked & 0x07 (e.g. "0xC0E0 & 0x07") // where a is the address poked & 0x07 (e.g. "0xC0E0 & 0x07")
void DiskII::step(uint8_t phase) void DiskII::step(uint8_t a)
{ {
static int mag[4] = { 0,0,0,0 }; int phase = (a >> 1) & 3;
static int pmag[4] = { 0, 0, 0, 0 }; int phase_bit = (1 << phase);
static int ppmag[4] = { 0, 0, 0, 0 };
static int pnum = 0;
static int ppnum = 0;
static int trackPos = 0;
static int prevTrack = 0;
// phase &= 7; if (a & 1) {
int magnet_number = phase >> 1; stepperPhases[selectedDisk] |= phase_bit;
// shuffle data down
ppmag[ppnum] = pmag[ppnum];
ppnum = pnum;
pmag[pnum] = mag[pnum];
pnum = magnet_number;
if ((phase & 1) == 0) {
mag[magnet_number] = 0;
} else { } else {
if (ppmag[(magnet_number + 1) & 3]) { stepperPhases[selectedDisk] &= ~phase_bit;
if (--trackPos < 0) {
trackPos = 0;
// recalibrate...
}
}
if (ppmag[(magnet_number - 1) & 3]) {
// FIXME: don't go beyond the end of the media. For a 35-track disk, that's 68 == ((35-1) * 2).
if (++trackPos > 68) {
trackPos = 68;
}
}
mag[magnet_number] = 1;
} }
curTrack = (trackPos + 1) / 2; // If the magnet opposite the cog is off, then try to move. Move in
if (curTrack != prevTrack) { // the direction of adjacent magent - but if both adjacent magents
// We're about to change tracks - be sure to flush the track if we've written to it // are on, then don't move at all.
checkFlush(prevTrack); int direction = 0;
int cur_phase = curPhase[selectedDisk];
if (stepperPhases[selectedDisk] & (1 << ((cur_phase + 1) & 3))) {
direction++;
}
if (stepperPhases[selectedDisk] & (1 << ((cur_phase+3) & 3))) {
direction--;
}
if (direction) {
int next_phase = cur_phase + direction;
if (next_phase < 0) {
next_phase = 0;
// recalibrate
}
// FIXME: don't go beyond the end of the media. For a 35-track disk, that's 68 == ((35-1) * 2).
if (next_phase > 69) {
next_phase = 69;
// ... Or go to 79? or 68, which we stopped at before? Not sure
// what the right behavior is here.
}
if ((cur_phase >> 1) != (next_phase >> 1)) {
// We're about to change tracks - be sure to flush the track if we've written to it
checkFlush(prevTrack[selectedDisk]);
prevTrack[selectedDisk] = curTrack[selectedDisk];
curTrack[selectedDisk] = next_phase>>1;
// mark it to be read
trackToRead = curTrack[selectedDisk];
}
curPhase[selectedDisk] = next_phase;
// step to the appropriate track
prevTrack = curTrack;
// mark it to be read
trackToRead = curTrack;
} }
} }
@ -317,7 +329,7 @@ void DiskII::select(int8_t which)
indicatorIsOn[selectedDisk] = 0; indicatorIsOn[selectedDisk] = 0;
g_display->setDriveIndicator(selectedDisk, false); g_display->setDriveIndicator(selectedDisk, false);
checkFlush(curTrack); checkFlush(curTrack[selectedDisk]);
} }
// set the selected disk drive // set the selected disk drive
@ -378,12 +390,12 @@ uint8_t DiskII::readOrWriteByte()
// //
// Don't fill it right here, b/c we don't want to bog down the CPU // Don't fill it right here, b/c we don't want to bog down the CPU
// thread/ISR. // thread/ISR.
if (trackToRead == curTrack) {// waiting for a read to complete if (trackToRead == curTrack[selectedDisk]) {// waiting for a read to complete
return GAP; return GAP;
} }
if ((trackToRead != -1) || !trackBuffer->hasData()) { if ((trackToRead != -1) || !trackBuffer->hasData()) {
checkFlush(curTrack); checkFlush(curTrack[selectedDisk]);
// Need to read in a track of data and nibblize it. We'll return 0xFF // Need to read in a track of data and nibblize it. We'll return 0xFF
// until that completes. // until that completes.
@ -392,7 +404,7 @@ uint8_t DiskII::readOrWriteByte()
// one we're reading. When we finish the read, we'll need to check // one we're reading. When we finish the read, we'll need to check
// to be sure that we're still trying to read the same track that // to be sure that we're still trying to read the same track that
// we started with. // we started with.
trackToRead = curTrack; trackToRead = curTrack[selectedDisk];
// While we're waiting for the sector to come around, we'll return // While we're waiting for the sector to come around, we'll return
// GAP bytes. // GAP bytes.
@ -449,7 +461,7 @@ void DiskII::fillDiskBuffer()
return; return;
} }
nibblizeTrack(trackBuffer, rawTrackBuffer, diskType[diskWeAreUsing], curTrack); nibblizeTrack(trackBuffer, rawTrackBuffer, diskType[diskWeAreUsing], curTrack[selectedDisk]);
} }
// Make sure we're still intending to read the track we just read // Make sure we're still intending to read the track we just read
@ -504,7 +516,7 @@ void DiskII::flushTrack(int8_t track, int8_t sel)
return; return;
} }
nibErr e = denibblizeTrack(trackBuffer, rawTrackBuffer, diskType[sel], curTrack); nibErr e = denibblizeTrack(trackBuffer, rawTrackBuffer, diskType[sel], curTrack[selectedDisk]);
switch (e) { switch (e) {
case errorShortTrack: case errorShortTrack:
g_display->debugMsg("DII: short track"); g_display->debugMsg("DII: short track");

View File

@ -48,7 +48,7 @@ class DiskII : public Slot {
#endif #endif
private: private:
volatile uint8_t curTrack; volatile uint8_t curTrack[2];
volatile bool trackDirty; // does this track need flushing to disk? volatile bool trackDirty; // does this track need flushing to disk?
uint8_t readWriteLatch; uint8_t readWriteLatch;
RingBuffer *trackBuffer; // nibblized data RingBuffer *trackBuffer; // nibblized data
@ -58,6 +58,11 @@ class DiskII : public Slot {
bool writeProt; bool writeProt;
AppleMMU *mmu; AppleMMU *mmu;
int trackPos[2];
int prevTrack[2];
int stepperPhases[2];
int curPhase[2];
int8_t disk[2]; int8_t disk[2];
volatile uint8_t indicatorIsOn[2]; volatile uint8_t indicatorIsOn[2];
uint8_t diskType[2]; uint8_t diskType[2];