mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Fluxmaps can now be queried for a (cached) list of index marks. Tracks
now contain both the raw list of sectors and a deduplicated list, suitable for the visualiser.
This commit is contained in:
@@ -88,7 +88,7 @@ void renderLogMessage(
|
|||||||
std::set<std::shared_ptr<const Record>> rawRecords;
|
std::set<std::shared_ptr<const Record>> rawRecords;
|
||||||
for (const auto& track : m->tracks)
|
for (const auto& track : m->tracks)
|
||||||
{
|
{
|
||||||
rawSectors.insert(track->sectors.begin(), track->sectors.end());
|
rawSectors.insert(track->allSectors.begin(), track->allSectors.end());
|
||||||
rawRecords.insert(track->records.begin(), track->records.end());
|
rawRecords.insert(track->records.begin(), track->records.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ void renderLogMessage(
|
|||||||
m->sectors.begin(), m->sectors.end());
|
m->sectors.begin(), m->sectors.end());
|
||||||
std::sort(sectors.begin(), sectors.end(), sectorPointerSortPredicate);
|
std::sort(sectors.begin(), sectors.end(), sectorPointerSortPredicate);
|
||||||
|
|
||||||
for (const auto& sector : sectors)
|
for (const auto& sector : rawSectors)
|
||||||
r.add(fmt::format("{}.{}.{}{}",
|
r.add(fmt::format("{}.{}.{}{}",
|
||||||
sector->logicalCylinder,
|
sector->logicalCylinder,
|
||||||
sector->logicalHead,
|
sector->logicalHead,
|
||||||
@@ -180,7 +180,7 @@ private:
|
|||||||
_cache;
|
_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
void measureDiskRotation()
|
static nanoseconds_t measureDiskRotation()
|
||||||
{
|
{
|
||||||
log(BeginSpeedOperationLogMessage());
|
log(BeginSpeedOperationLogMessage());
|
||||||
|
|
||||||
@@ -220,6 +220,7 @@ void measureDiskRotation()
|
|||||||
error("Failed\nIs a disk in the drive?");
|
error("Failed\nIs a disk in the drive?");
|
||||||
|
|
||||||
log(EndSpeedOperationLogMessage{oneRevolution});
|
log(EndSpeedOperationLogMessage{oneRevolution});
|
||||||
|
return oneRevolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a set of sectors, deduplicates them sensibly (e.g. if there is a good
|
/* Given a set of sectors, deduplicates them sensibly (e.g. if there is a good
|
||||||
@@ -298,7 +299,7 @@ static CombinationResult combineRecordAndSectors(
|
|||||||
/* Add the sectors which were there. */
|
/* Add the sectors which were there. */
|
||||||
|
|
||||||
for (auto& track : tracks)
|
for (auto& track : tracks)
|
||||||
for (auto& sector : track->sectors)
|
for (auto& sector : track->allSectors)
|
||||||
track_sectors.push_back(sector);
|
track_sectors.push_back(sector);
|
||||||
|
|
||||||
/* Add the sectors which should be there. */
|
/* Add the sectors which should be there. */
|
||||||
@@ -399,6 +400,7 @@ static ReadGroupResult readGroup(const DiskLayout& diskLayout,
|
|||||||
fluxmap->bytes());
|
fluxmap->bytes());
|
||||||
|
|
||||||
auto flux = decoder.decodeToSectors(std::move(fluxmap), ptl);
|
auto flux = decoder.decodeToSectors(std::move(fluxmap), ptl);
|
||||||
|
flux->normalisedSectors = collectSectors(flux->allSectors);
|
||||||
tracks.push_back(flux);
|
tracks.push_back(flux);
|
||||||
|
|
||||||
/* Decode what we've got so far. */
|
/* Decode what we've got so far. */
|
||||||
@@ -707,6 +709,10 @@ void readDiskCommand(const DiskLayout& diskLayout,
|
|||||||
.push_back(track);
|
.push_back(track);
|
||||||
|
|
||||||
log(BeginOperationLogMessage{"Reading and decoding disk"});
|
log(BeginOperationLogMessage{"Reading and decoding disk"});
|
||||||
|
|
||||||
|
if (fluxSource.isHardware())
|
||||||
|
disk.rotationalPeriod = measureDiskRotation();
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_ptr<FluxSink> outputFluxSink;
|
std::unique_ptr<FluxSink> outputFluxSink;
|
||||||
if (outputFluxSinkFactory)
|
if (outputFluxSinkFactory)
|
||||||
|
|||||||
@@ -76,8 +76,6 @@ struct OperationProgressLogMessage
|
|||||||
unsigned progress;
|
unsigned progress;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void measureDiskRotation();
|
|
||||||
|
|
||||||
extern void writeTracks(const DiskLayout& diskLayout,
|
extern void writeTracks(const DiskLayout& diskLayout,
|
||||||
FluxSinkFactory& fluxSinkFactory,
|
FluxSinkFactory& fluxSinkFactory,
|
||||||
const std::function<std::unique_ptr<const Fluxmap>(
|
const std::function<std::unique_ptr<const Fluxmap>(
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ Disk::Disk(
|
|||||||
for (auto& [ch, sector] :
|
for (auto& [ch, sector] :
|
||||||
sectorsGroupedByTrack.equal_range(physicalLocation) | pair_to_range)
|
sectorsGroupedByTrack.equal_range(physicalLocation) | pair_to_range)
|
||||||
{
|
{
|
||||||
decodedTrack->sectors.push_back(sector);
|
decodedTrack->allSectors.push_back(sector);
|
||||||
|
decodedTrack->normalisedSectors.push_back(sector);
|
||||||
sectorsByPhysicalLocation.insert(
|
sectorsByPhysicalLocation.insert(
|
||||||
std::make_pair(physicalLocation, sector));
|
std::make_pair(physicalLocation, sector));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,14 @@ struct Track
|
|||||||
std::shared_ptr<const PhysicalTrackLayout> ptl;
|
std::shared_ptr<const PhysicalTrackLayout> ptl;
|
||||||
std::shared_ptr<const Fluxmap> fluxmap;
|
std::shared_ptr<const Fluxmap> fluxmap;
|
||||||
std::vector<std::shared_ptr<const Record>> records;
|
std::vector<std::shared_ptr<const Record>> records;
|
||||||
std::vector<std::shared_ptr<const Sector>> sectors;
|
|
||||||
|
/* All sectors, valid or not, including duplicates. */
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<const Sector>> allSectors;
|
||||||
|
|
||||||
|
/* Zero or one sector for each ID, preferring good ones. */
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<const Sector>> normalisedSectors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Disk
|
struct Disk
|
||||||
@@ -46,6 +53,10 @@ struct Disk
|
|||||||
std::multimap<CylinderHead, std::shared_ptr<const Sector>>
|
std::multimap<CylinderHead, std::shared_ptr<const Sector>>
|
||||||
sectorsByPhysicalLocation;
|
sectorsByPhysicalLocation;
|
||||||
std::shared_ptr<const Image> image;
|
std::shared_ptr<const Image> image;
|
||||||
|
|
||||||
|
/* 0 if the period is unknown (e.g. if this Disk was made from an image). */
|
||||||
|
|
||||||
|
nanoseconds_t rotationalPeriod = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "lib/core/globals.h"
|
#include "lib/core/globals.h"
|
||||||
#include "lib/data/fluxmap.h"
|
#include "lib/data/fluxmap.h"
|
||||||
|
#include "lib/data/fluxmapreader.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
Fluxmap& Fluxmap::appendBytes(const Bytes& bytes)
|
Fluxmap& Fluxmap::appendBytes(const Bytes& bytes)
|
||||||
{
|
{
|
||||||
@@ -12,6 +14,8 @@ Fluxmap& Fluxmap::appendBytes(const Bytes& bytes)
|
|||||||
|
|
||||||
Fluxmap& Fluxmap::appendBytes(const uint8_t* ptr, size_t len)
|
Fluxmap& Fluxmap::appendBytes(const uint8_t* ptr, size_t len)
|
||||||
{
|
{
|
||||||
|
flushIndexMarks();
|
||||||
|
|
||||||
ByteWriter bw(_bytes);
|
ByteWriter bw(_bytes);
|
||||||
bw.seekToEnd();
|
bw.seekToEnd();
|
||||||
|
|
||||||
@@ -52,6 +56,7 @@ Fluxmap& Fluxmap::appendPulse()
|
|||||||
|
|
||||||
Fluxmap& Fluxmap::appendIndex()
|
Fluxmap& Fluxmap::appendIndex()
|
||||||
{
|
{
|
||||||
|
flushIndexMarks();
|
||||||
findLastByte() |= 0x40;
|
findLastByte() |= 0x40;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -75,3 +80,27 @@ std::vector<std::unique_ptr<const Fluxmap>> Fluxmap::split() const
|
|||||||
|
|
||||||
return maps;
|
return maps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<nanoseconds_t>& Fluxmap::getIndexMarks() const
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(_mutationMutex);
|
||||||
|
if (!_indexMarks.has_value())
|
||||||
|
{
|
||||||
|
_indexMarks = std::make_optional<std::vector<nanoseconds_t>>();
|
||||||
|
FluxmapReader fmr(*this);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
unsigned ticks;
|
||||||
|
if (!fmr.findEvent(F_BIT_INDEX, ticks))
|
||||||
|
break;
|
||||||
|
_indexMarks->push_back(fmr.tell().ns());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *_indexMarks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fluxmap::flushIndexMarks()
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(_mutationMutex);
|
||||||
|
_indexMarks = {};
|
||||||
|
}
|
||||||
|
|||||||
@@ -82,14 +82,18 @@ public:
|
|||||||
std::unique_ptr<const Fluxmap> precompensate(
|
std::unique_ptr<const Fluxmap> precompensate(
|
||||||
int threshold_ticks, int amount_ticks);
|
int threshold_ticks, int amount_ticks);
|
||||||
std::vector<std::unique_ptr<const Fluxmap>> split() const;
|
std::vector<std::unique_ptr<const Fluxmap>> split() const;
|
||||||
|
const std::vector<nanoseconds_t>& getIndexMarks() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t& findLastByte();
|
uint8_t& findLastByte();
|
||||||
|
void flushIndexMarks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nanoseconds_t _duration = 0;
|
nanoseconds_t _duration = 0;
|
||||||
int _ticks = 0;
|
int _ticks = 0;
|
||||||
Bytes _bytes;
|
Bytes _bytes;
|
||||||
|
mutable std::mutex _mutationMutex;
|
||||||
|
mutable std::optional<std::vector<nanoseconds_t>> _indexMarks;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ void FluxmapReader::skipToEvent(int event)
|
|||||||
findEvent(event, ticks);
|
findEvent(event, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FluxmapReader::getCurrentEvent()
|
||||||
|
{
|
||||||
|
if (eof())
|
||||||
|
return F_EOF;
|
||||||
|
return _bytes[_pos.bytes] & 0xc0;
|
||||||
|
}
|
||||||
|
|
||||||
bool FluxmapReader::findEvent(int event, unsigned& ticks)
|
bool FluxmapReader::findEvent(int event, unsigned& ticks)
|
||||||
{
|
{
|
||||||
ticks = 0;
|
ticks = 0;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public:
|
|||||||
return (_fluxmap.duration());
|
return (_fluxmap.duration());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getCurrentEvent();
|
||||||
void getNextEvent(int& event, unsigned& ticks);
|
void getNextEvent(int& event, unsigned& ticks);
|
||||||
void skipToEvent(int event);
|
void skipToEvent(int event);
|
||||||
bool findEvent(int event, unsigned& ticks);
|
bool findEvent(int event, unsigned& ticks);
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ std::shared_ptr<Track> Decoder::decodeToSectors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_sector->status != Sector::MISSING)
|
if (_sector->status != Sector::MISSING)
|
||||||
_trackdata->sectors.push_back(_sector);
|
_trackdata->allSectors.push_back(_sector);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _trackdata;
|
return _trackdata;
|
||||||
|
|||||||
@@ -5,8 +5,11 @@
|
|||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "snowhouse/snowhouse.h"
|
||||||
|
|
||||||
static Fluxmap fluxmap(Bytes{F_DESYNC,
|
using namespace snowhouse;
|
||||||
|
|
||||||
|
static const Fluxmap fluxmap(Bytes{F_DESYNC,
|
||||||
F_BIT_PULSE | 0x30,
|
F_BIT_PULSE | 0x30,
|
||||||
F_BIT_INDEX | 0x30,
|
F_BIT_INDEX | 0x30,
|
||||||
F_BIT_PULSE | F_BIT_INDEX | 0x30,
|
F_BIT_PULSE | F_BIT_INDEX | 0x30,
|
||||||
@@ -59,7 +62,7 @@ void test_read_pulses()
|
|||||||
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x60);
|
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x60);
|
||||||
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x60);
|
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x60);
|
||||||
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x30);
|
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x30);
|
||||||
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x90);
|
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x90); /* EOF event */
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_read_indices()
|
void test_read_indices()
|
||||||
@@ -67,7 +70,7 @@ void test_read_indices()
|
|||||||
FluxmapReader fmr(fluxmap);
|
FluxmapReader fmr(fluxmap);
|
||||||
ASSERT_READ_SPECIFIC_EVENT(F_BIT_INDEX, 0x60);
|
ASSERT_READ_SPECIFIC_EVENT(F_BIT_INDEX, 0x60);
|
||||||
ASSERT_READ_SPECIFIC_EVENT(F_BIT_INDEX, 0x30);
|
ASSERT_READ_SPECIFIC_EVENT(F_BIT_INDEX, 0x30);
|
||||||
ASSERT_READ_SPECIFIC_EVENT(F_BIT_INDEX, 6 * 0x30);
|
ASSERT_READ_SPECIFIC_EVENT(F_BIT_INDEX, 6 * 0x30); /* EOF event */
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_read_desyncs()
|
void test_read_desyncs()
|
||||||
@@ -76,7 +79,13 @@ void test_read_desyncs()
|
|||||||
ASSERT_READ_SPECIFIC_EVENT(F_DESYNC, 0);
|
ASSERT_READ_SPECIFIC_EVENT(F_DESYNC, 0);
|
||||||
ASSERT_READ_SPECIFIC_EVENT(F_DESYNC, 0xf0);
|
ASSERT_READ_SPECIFIC_EVENT(F_DESYNC, 0xf0);
|
||||||
ASSERT_READ_SPECIFIC_EVENT(F_DESYNC, 0x60);
|
ASSERT_READ_SPECIFIC_EVENT(F_DESYNC, 0x60);
|
||||||
ASSERT_READ_SPECIFIC_EVENT(F_DESYNC, 0x60);
|
ASSERT_READ_SPECIFIC_EVENT(F_DESYNC, 0x60); /* EOF event */
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_index_marks()
|
||||||
|
{
|
||||||
|
AssertThat(fluxmap.getIndexMarks(),
|
||||||
|
Equals(std::vector<nanoseconds_t>{8000, 12000}));
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
@@ -85,5 +94,6 @@ int main(int argc, const char* argv[])
|
|||||||
test_read_pulses();
|
test_read_pulses();
|
||||||
test_read_indices();
|
test_read_indices();
|
||||||
test_read_desyncs();
|
test_read_desyncs();
|
||||||
|
test_index_marks();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user