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;
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());
}
@@ -113,7 +113,7 @@ void renderLogMessage(
m->sectors.begin(), m->sectors.end());
std::sort(sectors.begin(), sectors.end(), sectorPointerSortPredicate);
for (const auto& sector : sectors)
for (const auto& sector : rawSectors)
r.add(fmt::format("{}.{}.{}{}",
sector->logicalCylinder,
sector->logicalHead,
@@ -180,7 +180,7 @@ private:
_cache;
};
void measureDiskRotation()
static nanoseconds_t measureDiskRotation()
{
log(BeginSpeedOperationLogMessage());
@@ -220,6 +220,7 @@ void measureDiskRotation()
error("Failed\nIs a disk in the drive?");
log(EndSpeedOperationLogMessage{oneRevolution});
return oneRevolution;
}
/* 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. */
for (auto& track : tracks)
for (auto& sector : track->sectors)
for (auto& sector : track->allSectors)
track_sectors.push_back(sector);
/* Add the sectors which should be there. */
@@ -399,6 +400,7 @@ static ReadGroupResult readGroup(const DiskLayout& diskLayout,
fluxmap->bytes());
auto flux = decoder.decodeToSectors(std::move(fluxmap), ptl);
flux->normalisedSectors = collectSectors(flux->allSectors);
tracks.push_back(flux);
/* Decode what we've got so far. */
@@ -707,6 +709,10 @@ void readDiskCommand(const DiskLayout& diskLayout,
.push_back(track);
log(BeginOperationLogMessage{"Reading and decoding disk"});
if (fluxSource.isHardware())
disk.rotationalPeriod = measureDiskRotation();
{
std::unique_ptr<FluxSink> outputFluxSink;
if (outputFluxSinkFactory)

View File

@@ -76,8 +76,6 @@ struct OperationProgressLogMessage
unsigned progress;
};
extern void measureDiskRotation();
extern void writeTracks(const DiskLayout& diskLayout,
FluxSinkFactory& fluxSinkFactory,
const std::function<std::unique_ptr<const Fluxmap>(

View File

@@ -47,7 +47,8 @@ Disk::Disk(
for (auto& [ch, sector] :
sectorsGroupedByTrack.equal_range(physicalLocation) | pair_to_range)
{
decodedTrack->sectors.push_back(sector);
decodedTrack->allSectors.push_back(sector);
decodedTrack->normalisedSectors.push_back(sector);
sectorsByPhysicalLocation.insert(
std::make_pair(physicalLocation, sector));
}

View File

@@ -26,7 +26,14 @@ struct Track
std::shared_ptr<const PhysicalTrackLayout> ptl;
std::shared_ptr<const Fluxmap> fluxmap;
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
@@ -46,6 +53,10 @@ struct Disk
std::multimap<CylinderHead, std::shared_ptr<const Sector>>
sectorsByPhysicalLocation;
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

View File

@@ -1,6 +1,8 @@
#include "lib/core/globals.h"
#include "lib/data/fluxmap.h"
#include "lib/data/fluxmapreader.h"
#include "protocol.h"
#include <mutex>
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)
{
flushIndexMarks();
ByteWriter bw(_bytes);
bw.seekToEnd();
@@ -52,6 +56,7 @@ Fluxmap& Fluxmap::appendPulse()
Fluxmap& Fluxmap::appendIndex()
{
flushIndexMarks();
findLastByte() |= 0x40;
return *this;
}
@@ -75,3 +80,27 @@ std::vector<std::unique_ptr<const Fluxmap>> Fluxmap::split() const
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(
int threshold_ticks, int amount_ticks);
std::vector<std::unique_ptr<const Fluxmap>> split() const;
const std::vector<nanoseconds_t>& getIndexMarks() const;
private:
uint8_t& findLastByte();
void flushIndexMarks();
private:
nanoseconds_t _duration = 0;
int _ticks = 0;
Bytes _bytes;
mutable std::mutex _mutationMutex;
mutable std::optional<std::vector<nanoseconds_t>> _indexMarks;
};
#endif

View File

@@ -44,6 +44,13 @@ void FluxmapReader::skipToEvent(int event)
findEvent(event, ticks);
}
int FluxmapReader::getCurrentEvent()
{
if (eof())
return F_EOF;
return _bytes[_pos.bytes] & 0xc0;
}
bool FluxmapReader::findEvent(int event, unsigned& ticks)
{
ticks = 0;

View File

@@ -42,6 +42,7 @@ public:
return (_fluxmap.duration());
}
int getCurrentEvent();
void getNextEvent(int& event, unsigned& ticks);
void skipToEvent(int event);
bool findEvent(int event, unsigned& ticks);

View File

@@ -90,7 +90,7 @@ std::shared_ptr<Track> Decoder::decodeToSectors(
}
if (_sector->status != Sector::MISSING)
_trackdata->sectors.push_back(_sector);
_trackdata->allSectors.push_back(_sector);
}
return _trackdata;

View File

@@ -5,8 +5,11 @@
#include "fmt/format.h"
#include "tests.h"
#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_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, 0x30);
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x90);
ASSERT_READ_SPECIFIC_EVENT(F_BIT_PULSE, 0x90); /* EOF event */
}
void test_read_indices()
@@ -67,7 +70,7 @@ void test_read_indices()
FluxmapReader fmr(fluxmap);
ASSERT_READ_SPECIFIC_EVENT(F_BIT_INDEX, 0x60);
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()
@@ -76,7 +79,13 @@ void test_read_desyncs()
ASSERT_READ_SPECIFIC_EVENT(F_DESYNC, 0);
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); /* EOF event */
}
void test_index_marks()
{
AssertThat(fluxmap.getIndexMarks(),
Equals(std::vector<nanoseconds_t>{8000, 12000}));
}
int main(int argc, const char* argv[])
@@ -85,5 +94,6 @@ int main(int argc, const char* argv[])
test_read_pulses();
test_read_indices();
test_read_desyncs();
test_index_marks();
return 0;
}