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:
David Given
2025-10-16 00:52:37 +02:00
parent 6d75feb0ce
commit 87ce3ad61d
10 changed files with 80 additions and 13 deletions

View File

@@ -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)

View File

@@ -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>(

View File

@@ -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));
} }

View File

@@ -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

View File

@@ -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 = {};
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
} }