Fixed incorrect cycle calculation and removed floats entirely in drive loop

Replace incorrect cyclesLeft calculation with faster non-floating point error calculator. Replaced modulo calculation with faster size comparison.
This commit is contained in:
Alexander Martinelle 2019-09-07 14:27:32 +02:00
parent 2d538e4975
commit 8875c55c25
2 changed files with 26 additions and 17 deletions

View file

@ -487,8 +487,10 @@ bool Drive::Update()
DriveLoopReadNoCycles(); DriveLoopReadNoCycles();
} }
else else
{
DriveLoopRead(); DriveLoopRead();
} }
}
#else #else
for (int cycles = 0; cycles < 16; ++cycles) for (int cycles = 0; cycles < 16; ++cycles)
{ {
@ -580,6 +582,7 @@ bool Drive::Update()
return dataReady; return dataReady;
} }
#if defined(EXPERIMENTALZERO) #if defined(EXPERIMENTALZERO)
#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))
@ -597,7 +600,6 @@ void Drive::DriveLoopReadNoFluxNoCycles()
cycles = 0; cycles = 0;
return; return;
} }
cycles -= UE7Counter; 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. 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.
@ -649,14 +651,8 @@ void Drive::DriveLoopReadNoFlux()
if (cyclesLeftForBit == 0) if (cyclesLeftForBit == 0)
{ {
//which is faster? single loop ceil check or the 3 lines below? cyclesForBitErrorCounter -= cyclesPerBitErrorConstant;
float fn = 2.0f * cyclesPerBit - cyclesForBit; cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant);
cyclesLeftForBit = (int)fn;
cyclesForBit = cyclesPerBit;
if (fn != (float)cyclesLeftForBit) {
++cyclesLeftForBit;
++cyclesForBit;
}
//cyclesForBit -= cyclesPerBit; //cyclesForBit -= cyclesPerBit;
//cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit); //cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit);
@ -772,13 +768,8 @@ void Drive::DriveLoopRead()
if (cyclesLeftForBit == 0) if (cyclesLeftForBit == 0)
{ {
//which is faster? single loop ceil check or the 3 lines below? //which is faster? single loop ceil check or the 3 lines below?
float fn = 2.0f * cyclesPerBit - cyclesForBit; cyclesForBitErrorCounter -= cyclesPerBitErrorConstant;
cyclesLeftForBit = (int)fn; cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant);
cyclesForBit = cyclesPerBit;
if (fn != (float)cyclesLeftForBit) {
++cyclesLeftForBit;
++cyclesForBit;
}
//cyclesForBit -= cyclesPerBit; //cyclesForBit -= cyclesPerBit;
//cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit); //cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit);

View file

@ -96,6 +96,12 @@ private:
bitsInTrack = diskImage->BitsInTrack(headTrackPos); bitsInTrack = diskImage->BitsInTrack(headTrackPos);
headBitOffset %= bitsInTrack; headBitOffset %= bitsInTrack;
cyclesPerBit = CYCLES_16Mhz_PER_ROTATION / (float)bitsInTrack; cyclesPerBit = CYCLES_16Mhz_PER_ROTATION / (float)bitsInTrack;
#if defined(EXPERIMENTALZERO)
cyclesPerBitInt = cyclesPerBit;
cyclesPerBitErrorConstant = (unsigned int)((cyclesPerBit - ((float)cyclesPerBitInt)) * static_cast<float>(0xffffffff));
cyclesForBitErrorCounter = (unsigned int)(((cyclesForBit)-(int)(cyclesForBit)) * static_cast<float>(0xffffffff));
#endif
} }
inline void MoveHead(unsigned char headDirection) inline void MoveHead(unsigned char headDirection)
@ -118,6 +124,15 @@ private:
void DumpTrack(unsigned track); // Used for debugging disk images. void DumpTrack(unsigned track); // Used for debugging disk images.
#if defined(EXPERIMENTALZERO)
inline u32 AdvanceSectorPositionR(int& byteOffset)
{
if (++headBitOffset == bitsInTrack)
headBitOffset = 0;
byteOffset = headBitOffset >> 3;
return (~headBitOffset) & 7;
}
#else
// No reason why I seperate these into individual read and write versions. I was just trying to get the bit stream to line up when rewriting over existing data. // No reason why I seperate these into individual read and write versions. I was just trying to get the bit stream to line up when rewriting over existing data.
inline u32 AdvanceSectorPositionR(int& byteOffset) inline u32 AdvanceSectorPositionR(int& byteOffset)
{ {
@ -125,7 +140,7 @@ private:
byteOffset = headBitOffset >> 3; byteOffset = headBitOffset >> 3;
return (~headBitOffset) & 7; return (~headBitOffset) & 7;
} }
#endif
inline u32 AdvanceSectorPositionW(int& byteOffset) inline u32 AdvanceSectorPositionW(int& byteOffset)
{ {
byteOffset = headBitOffset >> 3; byteOffset = headBitOffset >> 3;
@ -167,6 +182,9 @@ private:
unsigned int fluxReversalCyclesLeft; unsigned int fluxReversalCyclesLeft;
unsigned int UE7Counter; unsigned int UE7Counter;
u32 writeShiftRegister; u32 writeShiftRegister;
unsigned int cyclesForBitErrorCounter;
unsigned int cyclesPerBitErrorConstant;
unsigned int cyclesPerBitInt;
#else #else
int UE7Counter; int UE7Counter;
u8 writeShiftRegister; u8 writeShiftRegister;