1541 Drive speed improvements
Specialized drive read loops for the most common cases, triggers a vast speed improvement in some scenarios. Improved saving speed. Removed some more code that's not really required right now.
This commit is contained in:
parent
bddc9a7d29
commit
3978ef2165
5 changed files with 259 additions and 55 deletions
268
src/Drive.cpp
268
src/Drive.cpp
|
@ -358,6 +358,7 @@ void Drive::Reset()
|
||||||
#if defined(EXPERIMENTALZERO)
|
#if defined(EXPERIMENTALZERO)
|
||||||
LED = false;
|
LED = false;
|
||||||
cyclesForBit = 0;
|
cyclesForBit = 0;
|
||||||
|
UE7Counter = 16;
|
||||||
#endif
|
#endif
|
||||||
headTrackPos = 18*2; // Start with the head over track 19 (Very later Vorpal ie Cakifornia Games) need to have had the last head movement -ve
|
headTrackPos = 18*2; // Start with the head over track 19 (Very later Vorpal ie Cakifornia Games) need to have had the last head movement -ve
|
||||||
CLOCK_SEL_AB = 3; // Track 18 will use speed zone 3 (encoder/decoder (ie UE7Counter) clocked at 1.2307Mhz)
|
CLOCK_SEL_AB = 3; // Track 18 will use speed zone 3 (encoder/decoder (ie UE7Counter) clocked at 1.2307Mhz)
|
||||||
|
@ -568,20 +569,71 @@ bool Drive::Update()
|
||||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
void Drive::DriveLoopRead()
|
void Drive::DriveLoopReadNoFluxNoCycles()
|
||||||
|
{
|
||||||
|
unsigned int cycles = 16;
|
||||||
|
fluxReversalCyclesLeft -= 16;
|
||||||
|
cyclesLeftForBit -= 16;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (cycles < UE7Counter)
|
||||||
|
{
|
||||||
|
UE7Counter -= cycles;
|
||||||
|
cycles = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cycles -= UE7Counter;
|
||||||
|
|
||||||
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
// - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0)
|
||||||
|
if ((UF4Counter & 0x3) == 2)
|
||||||
|
{
|
||||||
|
readShiftRegister <<= 1;
|
||||||
|
readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell)
|
||||||
|
|
||||||
|
writeShiftRegister <<= 1;
|
||||||
|
// Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs.
|
||||||
|
if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC
|
||||||
|
{
|
||||||
|
UE3Counter = 0; // Phase lock on to byte boundary
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits
|
||||||
|
UE3Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
||||||
|
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
||||||
|
{
|
||||||
|
UE3Counter = 0;
|
||||||
|
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
||||||
|
writeShiftRegister = (u8)(readShiftRegister & 0xff);
|
||||||
|
m_pVIA->GetPortA()->SetInput(writeShiftRegister);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Drive::DriveLoopReadNoFlux()
|
||||||
{
|
{
|
||||||
unsigned int minCycles;
|
unsigned int minCycles;
|
||||||
unsigned int cycles = 0;
|
unsigned int cycles = 16;
|
||||||
|
|
||||||
|
fluxReversalCyclesLeft -= 16;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
minCycles = min(min(cyclesLeftForBit, fluxReversalCyclesLeft), 16 - max(UE7Counter, cycles));
|
minCycles = min(min(cyclesLeftForBit, cycles), UE7Counter);
|
||||||
cyclesLeftForBit -= minCycles;
|
cyclesLeftForBit -= minCycles;
|
||||||
fluxReversalCyclesLeft -= minCycles;
|
cycles -= minCycles;
|
||||||
cycles += minCycles;
|
UE7Counter -= minCycles;
|
||||||
UE7Counter += minCycles;
|
|
||||||
|
|
||||||
if (cycles == 16)
|
if (cycles == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cyclesLeftForBit == 0)
|
if (cyclesLeftForBit == 0)
|
||||||
|
@ -605,14 +657,9 @@ void Drive::DriveLoopRead()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluxReversalCyclesLeft == 0)//Not entirely right, a flux reversal will be skipped if a bit read was going to happen
|
if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4.
|
||||||
{
|
{
|
||||||
ResetEncoderDecoder(2 * 16, /*25 * 16*/23 * 16); // Trigger a random noise generated zero crossing and start seeing more anywhere between 2us and 25us after this one.
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
}
|
|
||||||
|
|
||||||
if (UE7Counter == 0x10) // The count carry (bit 4) clocks UF4.
|
|
||||||
{
|
|
||||||
UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
|
||||||
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
@ -644,21 +691,32 @@ void Drive::DriveLoopRead()
|
||||||
m_pVIA->GetPortA()->SetInput(writeShiftRegister);
|
m_pVIA->GetPortA()->SetInput(writeShiftRegister);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
void Drive::DriveLoopReadNoCycles()
|
||||||
void Drive::DriveLoopWrite()
|
|
||||||
{
|
{
|
||||||
const unsigned int cycleStep = 16 - CLOCK_SEL_AB;
|
unsigned int minCycles;
|
||||||
unsigned int cycles = 16 - UE7Counter;
|
unsigned int cycles = 16;
|
||||||
while(cycles < 16)
|
|
||||||
|
cyclesLeftForBit -= 16;
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
//No check is required. This loops is all about the UE7Counter.
|
minCycles = min(cycles, min(UE7Counter, fluxReversalCyclesLeft));
|
||||||
//if (UE7Counter == 0x10) // The count carry (bit 4) clocks UF4.
|
fluxReversalCyclesLeft -= minCycles;
|
||||||
|
cycles -= minCycles;
|
||||||
|
UE7Counter -= minCycles;
|
||||||
|
|
||||||
|
if (cycles == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fluxReversalCyclesLeft == 0)//Not entirely right, a flux reversal will be skipped if a bit read was going to happen
|
||||||
{
|
{
|
||||||
UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
ResetEncoderDecoder(2 * 16, /*25 * 16*/23 * 16); // Trigger a random noise generated zero crossing and start seeing more anywhere between 2us and 25us after this one.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4.
|
||||||
|
{
|
||||||
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
@ -668,28 +726,166 @@ void Drive::DriveLoopWrite()
|
||||||
readShiftRegister <<= 1;
|
readShiftRegister <<= 1;
|
||||||
readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell)
|
readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell)
|
||||||
|
|
||||||
SetNextBit((writeShiftRegister & 0x80));
|
|
||||||
|
|
||||||
writeShiftRegister <<= 1;
|
writeShiftRegister <<= 1;
|
||||||
// Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs.
|
// Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs.
|
||||||
UE3Counter++;
|
if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC
|
||||||
|
{
|
||||||
|
UE3Counter = 0; // Phase lock on to byte boundary
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits
|
||||||
|
UE3Counter++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
||||||
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
||||||
{
|
{
|
||||||
UE3Counter = 0;
|
UE3Counter = 0;
|
||||||
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
||||||
writeShiftRegister = m_pVIA->GetPortA()->GetOutput();
|
writeShiftRegister = (u8)(readShiftRegister & 0xff);
|
||||||
}
|
m_pVIA->GetPortA()->SetInput(writeShiftRegister);
|
||||||
|
|
||||||
if ((16-cycles) < cycleStep)
|
|
||||||
{
|
|
||||||
UE7Counter += 16 - cycles;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UE7Counter += cycleStep;
|
};
|
||||||
cycles += cycleStep;
|
}
|
||||||
|
void Drive::DriveLoopRead()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (fluxReversalCyclesLeft > 16 && cyclesLeftForBit > 16)
|
||||||
|
{
|
||||||
|
DriveLoopReadNoFluxNoCycles();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fluxReversalCyclesLeft > 16)
|
||||||
|
{
|
||||||
|
DriveLoopReadNoFlux();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cyclesLeftForBit > 16)
|
||||||
|
{
|
||||||
|
DriveLoopReadNoCycles();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int minCycles;
|
||||||
|
unsigned int cycles = 16;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
minCycles = min(min(cyclesLeftForBit, cycles), min(UE7Counter, fluxReversalCyclesLeft));
|
||||||
|
cyclesLeftForBit -= minCycles;
|
||||||
|
fluxReversalCyclesLeft -= minCycles;
|
||||||
|
cycles -= minCycles;
|
||||||
|
UE7Counter -= minCycles;
|
||||||
|
|
||||||
|
if (cycles == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cyclesLeftForBit == 0)
|
||||||
|
{
|
||||||
|
//which is faster? single loop ceil check or the 3 lines below?
|
||||||
|
float fn = 2.0f * cyclesPerBit - cyclesForBit;
|
||||||
|
cyclesLeftForBit = (int)fn;
|
||||||
|
cyclesForBit = cyclesPerBit;
|
||||||
|
if (fn != (float)cyclesLeftForBit) {
|
||||||
|
++cyclesLeftForBit;
|
||||||
|
++cyclesForBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cyclesForBit -= cyclesPerBit;
|
||||||
|
//cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit);
|
||||||
|
//cyclesForBit += cyclesLeftForBit;
|
||||||
|
|
||||||
|
if (GetNextBit())
|
||||||
|
{
|
||||||
|
ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fluxReversalCyclesLeft == 0)//Not entirely right, a flux reversal will be skipped if a bit read was going to happen
|
||||||
|
{
|
||||||
|
ResetEncoderDecoder(2 * 16, /*25 * 16*/23 * 16); // Trigger a random noise generated zero crossing and start seeing more anywhere between 2us and 25us after this one.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4.
|
||||||
|
{
|
||||||
|
UE7Counter = 16-CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
// - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0)
|
||||||
|
//if ((UF4Counter & 0x3) == 2)
|
||||||
|
if (UF4Counter == 2 || UF4Counter == 6) //You'd think the bit operation should be faster...
|
||||||
|
{
|
||||||
|
readShiftRegister <<= 1;
|
||||||
|
readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell)
|
||||||
|
|
||||||
|
writeShiftRegister <<= 1;
|
||||||
|
// Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs.
|
||||||
|
if (((readShiftRegister & 0x3ff) == 0x3ff)) // if the last 10 bits are 1s then SYNC
|
||||||
|
{
|
||||||
|
UE3Counter = 0; // Phase lock on to byte boundary
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, false); // PB7 active low SYNC
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pVIA->GetPortB()->SetInput(0x80, true); // SYNC not asserted if not following the SYNC bits
|
||||||
|
UE3Counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
||||||
|
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
||||||
|
{
|
||||||
|
UE3Counter = 0;
|
||||||
|
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
||||||
|
writeShiftRegister = (u8)(readShiftRegister & 0xff);
|
||||||
|
m_pVIA->GetPortA()->SetInput(writeShiftRegister);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Drive::DriveLoopWrite()
|
||||||
|
{
|
||||||
|
unsigned int cycles = 16;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
if (cycles < UE7Counter)
|
||||||
|
{
|
||||||
|
UE7Counter -= cycles;
|
||||||
|
cycles = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cycles -= UE7Counter;
|
||||||
|
|
||||||
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6) ie preload the encoder/decoder clock for the current density settings.
|
||||||
|
// The decoder consists of UF4 and UE5A. The ecoder has two outputs, Pin 1 of UE5A is the serial data output and pin 2 of UF4 (output B) is the serial clock output.
|
||||||
|
++UF4Counter &= 0xf; // Clock and clamp UF4.
|
||||||
|
// The UD2 read shift register is clocked by serial clock (the rising edge of encoder/decoder's UF4 B output (serial clock))
|
||||||
|
// - ie on counts 2, 6, 10 and 14 (2 is the only count that outputs a 1 into readShiftRegister as the MSB bits of the count NORed together for other values are 0)
|
||||||
|
if ((UF4Counter & 0x3) == 2)
|
||||||
|
{
|
||||||
|
readShiftRegister <<= 1;
|
||||||
|
readShiftRegister |= (UF4Counter == 2); // Emulate UE5A and only shift in a 1 when pins 6 (output C) and 7 (output D) (bits 2 and 3 of UF4Counter are 0. ie the first count of the bit cell)
|
||||||
|
|
||||||
|
SetNextBit((writeShiftRegister & 0x80));
|
||||||
|
|
||||||
|
writeShiftRegister <<= 1;
|
||||||
|
// Note: SYNC can only trigger during reading as R/!W line is one of UC2's inputs.
|
||||||
|
UE3Counter++;
|
||||||
|
}
|
||||||
|
// UC5B (NOR used to invert UF4's output B serial clock) output high when UF4 counts 0,1,4,5,8,9,12 and 13
|
||||||
|
else if (((UF4Counter & 2) == 0) && (UE3Counter == 8)) // Phase locked on to byte boundary
|
||||||
|
{
|
||||||
|
UE3Counter = 0;
|
||||||
|
SO = (m_pVIA->GetFCR() & m6522::FCR_CA2_OUTPUT_MODE0) != 0; // bit 2 of the FCR indicates "Byte Ready Active" turned on or not.
|
||||||
|
writeShiftRegister = m_pVIA->GetPortA()->GetOutput();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -51,6 +51,9 @@ public:
|
||||||
#if defined(EXPERIMENTALZERO)
|
#if defined(EXPERIMENTALZERO)
|
||||||
void DriveLoopWrite();
|
void DriveLoopWrite();
|
||||||
void DriveLoopRead();
|
void DriveLoopRead();
|
||||||
|
void DriveLoopReadNoFluxNoCycles();
|
||||||
|
void DriveLoopReadNoFlux();
|
||||||
|
void DriveLoopReadNoCycles();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Insert(DiskImage* diskImage);
|
void Insert(DiskImage* diskImage);
|
||||||
|
@ -69,7 +72,7 @@ private:
|
||||||
int32_t localSeed;
|
int32_t localSeed;
|
||||||
inline void ResetEncoderDecoder(unsigned int min, unsigned int /*max*/span)
|
inline void ResetEncoderDecoder(unsigned int min, unsigned int /*max*/span)
|
||||||
{
|
{
|
||||||
UE7Counter = CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6)
|
UE7Counter = 16 - CLOCK_SEL_AB; // A and B inputs of UE7 come from the VIA's CLOCK SEL A/B outputs (ie PB5/6)
|
||||||
UF4Counter = 0;
|
UF4Counter = 0;
|
||||||
localSeed = ((localSeed * 1103515245) + 12345) & 0x7fffffff;
|
localSeed = ((localSeed * 1103515245) + 12345) & 0x7fffffff;
|
||||||
fluxReversalCyclesLeft = (span) * (localSeed >> 11) + min;
|
fluxReversalCyclesLeft = (span) * (localSeed >> 11) + min;
|
||||||
|
|
|
@ -93,6 +93,7 @@ extern u16 pc;
|
||||||
u8 read6502_1581(u16 address)
|
u8 read6502_1581(u16 address)
|
||||||
{
|
{
|
||||||
u8 value = 0;
|
u8 value = 0;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (address & 0x8000)
|
if (address & 0x8000)
|
||||||
{
|
{
|
||||||
value = roms.Read1581(address);
|
value = roms.Read1581(address);
|
||||||
|
@ -115,6 +116,7 @@ u8 read6502_1581(u16 address)
|
||||||
{
|
{
|
||||||
value = address >> 8; // Empty address bus
|
value = address >> 8; // Empty address bus
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +129,7 @@ u8 peek6502_1581(u16 address)
|
||||||
|
|
||||||
void write6502_1581(u16 address, const u8 value)
|
void write6502_1581(u16 address, const u8 value)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (address & 0x8000)
|
if (address & 0x8000)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -145,6 +148,7 @@ void write6502_1581(u16 address, const u8 value)
|
||||||
{
|
{
|
||||||
s_u8Memory[address & 0x1fff] = value;
|
s_u8Memory[address & 0x1fff] = value;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CIAPortA_OnPortOut(void* pUserData, unsigned char status)
|
static void CIAPortA_OnPortOut(void* pUserData, unsigned char status)
|
||||||
|
|
|
@ -277,7 +277,7 @@ public:
|
||||||
RPI_SetGpioPinFunction((rpi_gpio_pin_t)PIGPIO_OUT_SRQ, FS_OUTPUT);
|
RPI_SetGpioPinFunction((rpi_gpio_pin_t)PIGPIO_OUT_SRQ, FS_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
// Set up audio.
|
// Set up audio.
|
||||||
write32(CM_PWMDIV, CM_PASSWORD + 0x2000);
|
write32(CM_PWMDIV, CM_PASSWORD + 0x2000);
|
||||||
write32(CM_PWMCTL, CM_PASSWORD + CM_ENAB + CM_SRC_OSCILLATOR); // Use Default 100MHz Clock
|
write32(CM_PWMCTL, CM_PASSWORD + CM_ENAB + CM_SRC_OSCILLATOR); // Use Default 100MHz Clock
|
||||||
|
@ -285,7 +285,7 @@ public:
|
||||||
write32(PWM_RNG1, 0x1B4); // 8bit 44100Hz Mono
|
write32(PWM_RNG1, 0x1B4); // 8bit 44100Hz Mono
|
||||||
write32(PWM_RNG2, 0x1B4);
|
write32(PWM_RNG2, 0x1B4);
|
||||||
write32(PWM_CTL, PWM_USEF2 + PWM_PWEN2 + PWM_USEF1 + PWM_PWEN1 + PWM_CLRF1);
|
write32(PWM_CTL, PWM_USEF2 + PWM_PWEN2 + PWM_USEF1 + PWM_PWEN1 + PWM_CLRF1);
|
||||||
|
#endif
|
||||||
|
|
||||||
int buttonCount = sizeof(ButtonPinFlags) / sizeof(unsigned);
|
int buttonCount = sizeof(ButtonPinFlags) / sizeof(unsigned);
|
||||||
for (index = 0; index < buttonCount; ++index)
|
for (index = 0; index < buttonCount; ++index)
|
||||||
|
|
33
src/main.cpp
33
src/main.cpp
|
@ -101,7 +101,9 @@ u8 s_u8Memory[0xc000];
|
||||||
int numberOfUSBMassStorageDevices = 0;
|
int numberOfUSBMassStorageDevices = 0;
|
||||||
DiskCaddy diskCaddy;
|
DiskCaddy diskCaddy;
|
||||||
Pi1541 pi1541;
|
Pi1541 pi1541;
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
Pi1581 pi1581;
|
Pi1581 pi1581;
|
||||||
|
#endif
|
||||||
CEMMCDevice m_EMMC;
|
CEMMCDevice m_EMMC;
|
||||||
Screen screen;
|
Screen screen;
|
||||||
ScreenLCD* screenLCD = 0;
|
ScreenLCD* screenLCD = 0;
|
||||||
|
@ -118,8 +120,9 @@ bool USBKeyboardDetected = false;
|
||||||
bool selectedViaIECCommands = false;
|
bool selectedViaIECCommands = false;
|
||||||
u16 pc;
|
u16 pc;
|
||||||
|
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
SpinLock core0RefreshingScreen;
|
SpinLock core0RefreshingScreen;
|
||||||
|
#endif
|
||||||
unsigned int screenWidth = 1024;
|
unsigned int screenWidth = 1024;
|
||||||
unsigned int screenHeight = 768;
|
unsigned int screenHeight = 768;
|
||||||
|
|
||||||
|
@ -609,6 +612,7 @@ EmulatingMode BeginEmulating(FileBrowser* fileBrowser, const char* filenameForIc
|
||||||
DiskImage* diskImage = diskCaddy.SelectFirstImage();
|
DiskImage* diskImage = diskCaddy.SelectFirstImage();
|
||||||
if (diskImage)
|
if (diskImage)
|
||||||
{
|
{
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
if (diskImage->IsD81())
|
if (diskImage->IsD81())
|
||||||
{
|
{
|
||||||
pi1581.Insert(diskImage);
|
pi1581.Insert(diskImage);
|
||||||
|
@ -617,6 +621,7 @@ EmulatingMode BeginEmulating(FileBrowser* fileBrowser, const char* filenameForIc
|
||||||
return EMULATING_1581;
|
return EMULATING_1581;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
pi1541.drive.Insert(diskImage);
|
pi1541.drive.Insert(diskImage);
|
||||||
fileBrowser->DisplayDiskInfo(diskImage, filenameForIcon);
|
fileBrowser->DisplayDiskInfo(diskImage, filenameForIcon);
|
||||||
|
@ -668,7 +673,9 @@ void GlobalSetDeviceID(u8 id)
|
||||||
deviceID = id;
|
deviceID = id;
|
||||||
m_IEC_Commands.SetDeviceId(id);
|
m_IEC_Commands.SetDeviceId(id);
|
||||||
pi1541.SetDeviceID(id);
|
pi1541.SetDeviceID(id);
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
pi1581.SetDeviceID(id);
|
pi1581.SetDeviceID(id);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser)
|
void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser)
|
||||||
|
@ -712,10 +719,6 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
||||||
if (numberOfImagesMax > 10)
|
if (numberOfImagesMax > 10)
|
||||||
numberOfImagesMax = 10;
|
numberOfImagesMax = 10;
|
||||||
|
|
||||||
core0RefreshingScreen.Acquire();
|
|
||||||
diskCaddy.Display();
|
|
||||||
core0RefreshingScreen.Release();
|
|
||||||
|
|
||||||
inputMappings->directDiskSwapRequest = 0;
|
inputMappings->directDiskSwapRequest = 0;
|
||||||
// Force an update on all the buttons now before we start emulation mode.
|
// Force an update on all the buttons now before we start emulation mode.
|
||||||
IEC_Bus::ReadBrowseMode();
|
IEC_Bus::ReadBrowseMode();
|
||||||
|
@ -731,8 +734,6 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
||||||
pi1541.Reset(); // will call IEC_Bus::Reset();
|
pi1541.Reset(); // will call IEC_Bus::Reset();
|
||||||
IEC_Bus::OutputLED = false;
|
IEC_Bus::OutputLED = false;
|
||||||
IEC_Bus::LetSRQBePulledHigh();
|
IEC_Bus::LetSRQBePulledHigh();
|
||||||
float avgTimer = 0.0f;
|
|
||||||
|
|
||||||
ctBefore = read32(ARM_SYSTIMER_CLO);
|
ctBefore = read32(ARM_SYSTIMER_CLO);
|
||||||
|
|
||||||
//resetWhileEmulating = false;
|
//resetWhileEmulating = false;
|
||||||
|
@ -756,7 +757,6 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
||||||
}
|
}
|
||||||
bool buttonState = false;
|
bool buttonState = false;
|
||||||
bool prevButtonState = false;
|
bool prevButtonState = false;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -776,7 +776,7 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
||||||
}
|
}
|
||||||
|
|
||||||
m6502.Step(); // If the CPU reads or writes to the VIA then clk and data can change
|
m6502.Step(); // If the CPU reads or writes to the VIA then clk and data can change
|
||||||
|
|
||||||
if (refreshOutsAfterCPUStep)
|
if (refreshOutsAfterCPUStep)
|
||||||
IEC_Bus::RefreshOuts1541(); // Now output all outputs.
|
IEC_Bus::RefreshOuts1541(); // Now output all outputs.
|
||||||
|
|
||||||
|
@ -829,13 +829,13 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
||||||
|
|
||||||
prevButtonState = buttonState;
|
prevButtonState = buttonState;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ctAfter = read32(ARM_SYSTIMER_CLO);
|
ctAfter = read32(ARM_SYSTIMER_CLO);
|
||||||
} while (ctAfter == ctBefore); // Sync to the 1MHz clock
|
} while (ctAfter == ctBefore); // Sync to the 1MHz clock
|
||||||
|
|
||||||
|
|
||||||
ctBefore = ctAfter;
|
ctBefore = ctAfter;
|
||||||
IEC_Bus::ReadEmulationMode1541();
|
IEC_Bus::ReadEmulationMode1541();
|
||||||
|
|
||||||
IEC_Bus::RefreshOuts1541(); // Now output all outputs.
|
IEC_Bus::RefreshOuts1541(); // Now output all outputs.
|
||||||
|
@ -1274,8 +1274,9 @@ void emulator()
|
||||||
IEC_Bus::Reset();
|
IEC_Bus::Reset();
|
||||||
|
|
||||||
IEC_Bus::LetSRQBePulledHigh();
|
IEC_Bus::LetSRQBePulledHigh();
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
core0RefreshingScreen.Acquire();
|
core0RefreshingScreen.Acquire();
|
||||||
|
#endif
|
||||||
IEC_Bus::WaitMicroSeconds(100);
|
IEC_Bus::WaitMicroSeconds(100);
|
||||||
|
|
||||||
roms.ResetCurrentROMIndex();
|
roms.ResetCurrentROMIndex();
|
||||||
|
@ -1285,9 +1286,9 @@ void emulator()
|
||||||
fileBrowser->ClearSelections();
|
fileBrowser->ClearSelections();
|
||||||
|
|
||||||
fileBrowser->RefeshDisplay(); // Just redisplay the current folder.
|
fileBrowser->RefeshDisplay(); // Just redisplay the current folder.
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
core0RefreshingScreen.Release();
|
core0RefreshingScreen.Release();
|
||||||
|
#endif
|
||||||
selectedViaIECCommands = false;
|
selectedViaIECCommands = false;
|
||||||
|
|
||||||
inputMappings->Reset();
|
inputMappings->Reset();
|
||||||
|
@ -1590,7 +1591,7 @@ static void CheckOptions()
|
||||||
|
|
||||||
deviceID = (u8)options.GetDeviceID();
|
deviceID = (u8)options.GetDeviceID();
|
||||||
DEBUG_LOG("DeviceID = %d\r\n", deviceID);
|
DEBUG_LOG("DeviceID = %d\r\n", deviceID);
|
||||||
|
#if not defined(EXPERIMENTALZERO)
|
||||||
const char* FontROMName = options.GetRomFontName();
|
const char* FontROMName = options.GetRomFontName();
|
||||||
if (FontROMName)
|
if (FontROMName)
|
||||||
{
|
{
|
||||||
|
@ -1625,7 +1626,7 @@ static void CheckOptions()
|
||||||
//DEBUG_LOG("Read ROM %s from options\r\n", ROMName);
|
//DEBUG_LOG("Read ROM %s from options\r\n", ROMName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
const char* ROMName1581 = options.GetRomName1581();
|
const char* ROMName1581 = options.GetRomName1581();
|
||||||
if (ROMName1581)
|
if (ROMName1581)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue