Early bail-out of DriveLoopReadNoFlux
A couple of small optimizations that shouldn't make a difference but do such as: Addressing tracks as a single array. Caching a single byte instead of re-reading the array. (Note that caching 32bits did not improve but actually worsen things). Harsher interrupt disabling. Whitespace changes in main... Plus, early bail out from DriveLoopReadNoFlux.
This commit is contained in:
parent
8875c55c25
commit
9b38fc6d32
7 changed files with 117 additions and 13 deletions
|
@ -151,7 +151,12 @@ void DiskImage::Close()
|
||||||
|
|
||||||
void DiskImage::DumpTrack(unsigned track)
|
void DiskImage::DumpTrack(unsigned track)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char* src = &tracks[track << 13];
|
||||||
|
#else
|
||||||
unsigned char* src = tracks[track];
|
unsigned char* src = tracks[track];
|
||||||
|
#endif
|
||||||
unsigned trackLength = trackLengths[track];
|
unsigned trackLength = trackLengths[track];
|
||||||
DEBUG_LOG("track = %d trackLength = %d\r\n", track, trackLength);
|
DEBUG_LOG("track = %d trackLength = %d\r\n", track, trackLength);
|
||||||
for (unsigned index = 0; index < trackLength; ++index)
|
for (unsigned index = 0; index < trackLength; ++index)
|
||||||
|
@ -205,7 +210,11 @@ bool DiskImage::OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsig
|
||||||
for (unsigned halfTrackIndex = 0; halfTrackIndex < last_track * 2; ++halfTrackIndex)
|
for (unsigned halfTrackIndex = 0; halfTrackIndex < last_track * 2; ++halfTrackIndex)
|
||||||
{
|
{
|
||||||
unsigned char track = (halfTrackIndex >> 1);
|
unsigned char track = (halfTrackIndex >> 1);
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char* dest = &tracks[halfTrackIndex << 13];
|
||||||
|
#else
|
||||||
unsigned char* dest = tracks[halfTrackIndex];
|
unsigned char* dest = tracks[halfTrackIndex];
|
||||||
|
#endif
|
||||||
|
|
||||||
trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH;
|
trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH;
|
||||||
|
|
||||||
|
@ -800,7 +809,11 @@ bool DiskImage::OpenG64(const FILINFO* fileInfo, unsigned char* diskImage, unsig
|
||||||
//DEBUG_LOG("trackLength = %d offset = %d\r\n", trackLength, offset);
|
//DEBUG_LOG("trackLength = %d offset = %d\r\n", trackLength, offset);
|
||||||
trackData += 2;
|
trackData += 2;
|
||||||
trackLengths[track] = trackLength;
|
trackLengths[track] = trackLength;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
memcpy(&tracks[track << 13], trackData, trackLength);
|
||||||
|
#else
|
||||||
memcpy(tracks[track], trackData, trackLength);
|
memcpy(tracks[track], trackData, trackLength);
|
||||||
|
#endif
|
||||||
trackUsed[track] = true;
|
trackUsed[track] = true;
|
||||||
//DEBUG_LOG("%d has data\r\n", track);
|
//DEBUG_LOG("%d has data\r\n", track);
|
||||||
}
|
}
|
||||||
|
@ -899,7 +912,11 @@ bool DiskImage::WriteG64(char* name)
|
||||||
|
|
||||||
gcr_track[0] = (BYTE)(track_len % 256);
|
gcr_track[0] = (BYTE)(track_len % 256);
|
||||||
gcr_track[1] = (BYTE)(track_len / 256);
|
gcr_track[1] = (BYTE)(track_len / 256);
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
memcpy(buffer, &tracks[track << 13], track_len);
|
||||||
|
#else
|
||||||
memcpy(buffer, tracks[track], track_len);
|
memcpy(buffer, tracks[track], track_len);
|
||||||
|
#endif
|
||||||
|
|
||||||
memcpy(gcr_track + 2, buffer, track_len);
|
memcpy(gcr_track + 2, buffer, track_len);
|
||||||
bytesToWrite = G64_TRACK_MAXLEN + 2;
|
bytesToWrite = G64_TRACK_MAXLEN + 2;
|
||||||
|
@ -965,11 +982,19 @@ bool DiskImage::OpenNIB(const FILINFO* fileInfo, unsigned char* diskImage, unsig
|
||||||
|
|
||||||
unsigned char* nibdata = diskImage + (t_index * NIB_TRACK_LENGTH) + 0x100;
|
unsigned char* nibdata = diskImage + (t_index * NIB_TRACK_LENGTH) + 0x100;
|
||||||
int align;
|
int align;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
trackLengths[track] = extract_GCR_track(&tracks[track << 13], nibdata, &align
|
||||||
|
//, ALIGN_GAP
|
||||||
|
, ALIGN_NONE
|
||||||
|
, capacity_min[trackDensity[track]],
|
||||||
|
capacity_max[trackDensity[track]]);
|
||||||
|
#else
|
||||||
trackLengths[track] = extract_GCR_track(tracks[track], nibdata, &align
|
trackLengths[track] = extract_GCR_track(tracks[track], nibdata, &align
|
||||||
//, ALIGN_GAP
|
//, ALIGN_GAP
|
||||||
, ALIGN_NONE
|
, ALIGN_NONE
|
||||||
, capacity_min[trackDensity[track]],
|
, capacity_min[trackDensity[track]],
|
||||||
capacity_max[trackDensity[track]]);
|
capacity_max[trackDensity[track]]);
|
||||||
|
#endif
|
||||||
|
|
||||||
trackUsed[track] = true;
|
trackUsed[track] = true;
|
||||||
|
|
||||||
|
@ -1031,7 +1056,11 @@ bool DiskImage::WriteNIB()
|
||||||
{
|
{
|
||||||
if (trackUsed[track])
|
if (trackUsed[track])
|
||||||
{
|
{
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
if (f_write(&fp, &tracks[track << 13], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten)
|
||||||
|
#else
|
||||||
if (f_write(&fp, tracks[track], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten)
|
if (f_write(&fp, tracks[track], bytesToWrite, &bytesWritten) != FR_OK || bytesToWrite != bytesWritten)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
DEBUG_LOG("Cannot write track data.\r\n");
|
DEBUG_LOG("Cannot write track data.\r\n");
|
||||||
}
|
}
|
||||||
|
@ -1250,10 +1279,18 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in
|
||||||
unsigned char gcr[5];
|
unsigned char gcr[5];
|
||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
unsigned char* offset;
|
unsigned char* offset;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char* end = &tracks[track << 13] + trackLengths[track];
|
||||||
|
#else
|
||||||
unsigned char* end = tracks[track] + trackLengths[track];
|
unsigned char* end = tracks[track] + trackLengths[track];
|
||||||
|
#endif
|
||||||
|
|
||||||
shift = bitIndex & 7;
|
shift = bitIndex & 7;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
offset = &tracks[track << 13] + (bitIndex >> 3);
|
||||||
|
#else
|
||||||
offset = tracks[track] + (bitIndex >> 3);
|
offset = tracks[track] + (bitIndex >> 3);
|
||||||
|
#endif
|
||||||
|
|
||||||
byte = offset[0] << shift;
|
byte = offset[0] << shift;
|
||||||
for (i = 0; i < num; i++, buf += 4)
|
for (i = 0; i < num; i++, buf += 4)
|
||||||
|
@ -1262,7 +1299,11 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in
|
||||||
{
|
{
|
||||||
offset++;
|
offset++;
|
||||||
if (offset >= end)
|
if (offset >= end)
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
offset = &tracks[track << 13];
|
||||||
|
#else
|
||||||
offset = tracks[track];
|
offset = tracks[track];
|
||||||
|
#endif
|
||||||
|
|
||||||
if (shift)
|
if (shift)
|
||||||
{
|
{
|
||||||
|
@ -1282,7 +1323,11 @@ void DiskImage::DecodeBlock(unsigned track, int bitIndex, unsigned char* buf, in
|
||||||
int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStartIndex)
|
int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStartIndex)
|
||||||
{
|
{
|
||||||
int readShiftRegister = 0;
|
int readShiftRegister = 0;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char byte = tracks[(track << 13) + (bitIndex >> 3)] << (bitIndex & 7);
|
||||||
|
#else
|
||||||
unsigned char byte = tracks[track][bitIndex >> 3] << (bitIndex & 7);
|
unsigned char byte = tracks[track][bitIndex >> 3] << (bitIndex & 7);
|
||||||
|
#endif
|
||||||
bool prevBitZero = true;
|
bool prevBitZero = true;
|
||||||
|
|
||||||
while (maxBits--)
|
while (maxBits--)
|
||||||
|
@ -1314,7 +1359,11 @@ int DiskImage::FindSync(unsigned track, int bitIndex, int maxBits, int* syncStar
|
||||||
bitIndex++;
|
bitIndex++;
|
||||||
if (bitIndex >= MAX_TRACK_LENGTH * 8)
|
if (bitIndex >= MAX_TRACK_LENGTH * 8)
|
||||||
bitIndex = 0;
|
bitIndex = 0;
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
byte = tracks[(track << 13)+(bitIndex >> 3)];
|
||||||
|
#else
|
||||||
byte = tracks[track][bitIndex >> 3];
|
byte = tracks[track][bitIndex >> 3];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -78,19 +78,48 @@ public:
|
||||||
|
|
||||||
bool GetDecodedSector(u32 track, u32 sector, u8* buffer);
|
bool GetDecodedSector(u32 track, u32 sector, u8* buffer);
|
||||||
|
|
||||||
|
inline unsigned char GetNextByte(u32 track, u32 byte)
|
||||||
|
{
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
return tracks[(track << 13) + byte];
|
||||||
|
#else
|
||||||
|
return tracks[track][byte];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool GetNextBit(u32 track, u32 byte, u32 bit)
|
inline bool GetNextBit(u32 track, u32 byte, u32 bit)
|
||||||
{
|
{
|
||||||
//if (attachedImageSize == 0)
|
//if (attachedImageSize == 0)
|
||||||
// return 0;
|
// return 0;
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
return ((tracks[(track << 13) + byte] >> bit) & 1) != 0;
|
||||||
|
#else
|
||||||
return ((tracks[track][byte] >> bit) & 1) != 0;
|
return ((tracks[track][byte] >> bit) & 1) != 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void SetBit(u32 track, u32 byte, u32 bit, bool value)
|
inline void SetBit(u32 track, u32 byte, u32 bit, bool value)
|
||||||
{
|
{
|
||||||
if (attachedImageSize == 0)
|
if (attachedImageSize == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
u8 dataOld = tracks[(track << 13) + byte];
|
||||||
|
u8 bitMask = 1 << bit;
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
TestDirty(track, (dataOld & bitMask) == 0);
|
||||||
|
tracks[(track << 13) + byte] |= bitMask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TestDirty(track, (dataOld & bitMask) != 0);
|
||||||
|
tracks[(track << 13) + byte] &= bitMask;
|
||||||
|
}
|
||||||
|
#else
|
||||||
u8 dataOld = tracks[track][byte];
|
u8 dataOld = tracks[track][byte];
|
||||||
u8 bitMask = 1 << bit;
|
u8 bitMask = 1 << bit;
|
||||||
if (value)
|
if (value)
|
||||||
|
@ -103,6 +132,7 @@ public:
|
||||||
TestDirty(track, (dataOld & bitMask) != 0);
|
TestDirty(track, (dataOld & bitMask) != 0);
|
||||||
tracks[track][byte] &= ~bitMask;
|
tracks[track][byte] &= ~bitMask;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char SectorsPerTrack[42];
|
static const unsigned char SectorsPerTrack[42];
|
||||||
|
@ -160,7 +190,11 @@ public:
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
#if defined(EXPERIMENTALZERO)
|
||||||
|
unsigned char tracks[HALF_TRACK_COUNT * MAX_TRACK_LENGTH];
|
||||||
|
#else
|
||||||
unsigned char tracks[HALF_TRACK_COUNT][MAX_TRACK_LENGTH];
|
unsigned char tracks[HALF_TRACK_COUNT][MAX_TRACK_LENGTH];
|
||||||
|
#endif
|
||||||
unsigned char tracksD81[HALF_TRACK_COUNT][2][MAX_TRACK_LENGTH];
|
unsigned char tracksD81[HALF_TRACK_COUNT][2][MAX_TRACK_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -662,9 +662,17 @@ void Drive::DriveLoopReadNoFlux()
|
||||||
{
|
{
|
||||||
ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16);
|
ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16);
|
||||||
}
|
}
|
||||||
|
if (cycles < UE7Counter)
|
||||||
|
{
|
||||||
|
UE7Counter -= cycles;
|
||||||
|
cyclesLeftForBit -= cycles;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cyclesLeftForBit -= UE7Counter;
|
||||||
|
cycles -= UE7Counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UE7Counter == 0x0) // The count carry (bit 4) clocks UF4.
|
//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.
|
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.
|
||||||
|
@ -749,6 +757,7 @@ void Drive::DriveLoopReadNoCycles()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Drive::DriveLoopRead()
|
void Drive::DriveLoopRead()
|
||||||
{
|
{
|
||||||
unsigned int minCycles;
|
unsigned int minCycles;
|
||||||
|
@ -767,14 +776,9 @@ void Drive::DriveLoopRead()
|
||||||
|
|
||||||
if (cyclesLeftForBit == 0)
|
if (cyclesLeftForBit == 0)
|
||||||
{
|
{
|
||||||
//which is faster? single loop ceil check or the 3 lines below?
|
|
||||||
cyclesForBitErrorCounter -= cyclesPerBitErrorConstant;
|
cyclesForBitErrorCounter -= cyclesPerBitErrorConstant;
|
||||||
cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant);
|
cyclesLeftForBit = cyclesPerBitInt + (cyclesForBitErrorCounter < cyclesPerBitErrorConstant);
|
||||||
|
|
||||||
//cyclesForBit -= cyclesPerBit;
|
|
||||||
//cyclesLeftForBit = ceil(cyclesPerBit - cyclesForBit);
|
|
||||||
//cyclesForBit += cyclesLeftForBit;
|
|
||||||
|
|
||||||
if (GetNextBit())
|
if (GetNextBit())
|
||||||
{
|
{
|
||||||
ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16);
|
ResetEncoderDecoder(18 * 16, /*20 * 16*/ 2 * 16);
|
||||||
|
|
16
src/Drive.h
16
src/Drive.h
|
@ -148,12 +148,24 @@ private:
|
||||||
++headBitOffset %= bitsInTrack;
|
++headBitOffset %= bitsInTrack;
|
||||||
return bit;
|
return bit;
|
||||||
}
|
}
|
||||||
|
unsigned cachedheadTrackPos = -1;
|
||||||
|
int cachedbyteOffset = -1;
|
||||||
|
unsigned char cachedByte = 0;
|
||||||
inline bool GetNextBit()
|
inline bool GetNextBit()
|
||||||
{
|
{
|
||||||
int byteOffset;
|
int byteOffset;
|
||||||
int bit = AdvanceSectorPositionR(byteOffset);
|
int bit = AdvanceSectorPositionR(byteOffset);
|
||||||
return diskImage->GetNextBit(headTrackPos, byteOffset, bit);
|
|
||||||
|
//Why is it faster to check both conditions here than to update the cache when moving the head?
|
||||||
|
if (byteOffset != cachedbyteOffset || cachedheadTrackPos != headTrackPos)
|
||||||
|
{
|
||||||
|
cachedByte = diskImage->GetNextByte(headTrackPos, byteOffset);
|
||||||
|
cachedbyteOffset = byteOffset;
|
||||||
|
cachedheadTrackPos = headTrackPos;
|
||||||
|
|
||||||
|
}
|
||||||
|
return ((cachedByte >> bit) & 1) != 0;
|
||||||
|
//return diskImage->GetNextBit(headTrackPos, byteOffset, bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetNextBit(bool value)
|
inline void SetNextBit(bool value)
|
||||||
|
|
|
@ -39,7 +39,9 @@ void InterruptSystemInitialize()
|
||||||
write32(ARM_IC_IRQ_PENDING_2, read32(ARM_IC_IRQ_PENDING_2));
|
write32(ARM_IC_IRQ_PENDING_2, read32(ARM_IC_IRQ_PENDING_2));
|
||||||
|
|
||||||
DataMemBarrier();
|
DataMemBarrier();
|
||||||
#ifndef EXPERIMENTALZERO
|
#ifdef EXPERIMENTALZERO
|
||||||
|
DisableInterrupts();
|
||||||
|
#else
|
||||||
EnableInterrupts();
|
EnableInterrupts();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ extern "C" {
|
||||||
#include "bcm2835int.h"
|
#include "bcm2835int.h"
|
||||||
|
|
||||||
#define EnableInterrupts() __asm volatile ("cpsie i")
|
#define EnableInterrupts() __asm volatile ("cpsie i")
|
||||||
#define DisableInterrupts() __asm volatile ("cpsid i")
|
#define DisableInterrupts() __asm volatile ("cpsid ifa, #0x13")
|
||||||
|
|
||||||
typedef void IRQHandler(void* param);
|
typedef void IRQHandler(void* param);
|
||||||
|
|
||||||
|
|
|
@ -832,13 +832,16 @@ EXIT_TYPE Emulate1541(FileBrowser* fileBrowser)
|
||||||
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue