mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Partial conversion to do automatic scaling of flux based on the disk rotation
speed. Although, something seems to have broken for 5.25" disks.
This commit is contained in:
@@ -2,7 +2,7 @@ syntax = "proto2";
|
||||
|
||||
import "lib/common.proto";
|
||||
|
||||
// Next: 13
|
||||
// Next: 14
|
||||
message DriveProto
|
||||
{
|
||||
optional int32 drive = 1
|
||||
@@ -22,13 +22,15 @@ message DriveProto
|
||||
[ default = 81, (help) = "Number of tracks supported by drive" ];
|
||||
optional int32 heads = 8
|
||||
[ default = 2, (help) = "Number of heads supported by drive" ];
|
||||
optional int32 head_bias = 10 [
|
||||
optional int32 head_bias = 9 [
|
||||
default = 0,
|
||||
(help) = "Bias to apply to the head position (in tracks)"
|
||||
];
|
||||
optional int32 head_width = 11
|
||||
optional int32 head_width = 10
|
||||
[ default = 1, (help) = "Width of the head (in tracks)" ];
|
||||
optional int32 tpi = 9 [ default = 96, (help) = "TPI of drive" ];
|
||||
optional int32 tpi = 11 [ default = 96, (help) = "TPI of drive" ];
|
||||
optional double rotational_period_ms = 12
|
||||
[ default = 0, (help) = "Rotational period of the drive in milliseconds (0 to autodetect)"];
|
||||
}
|
||||
|
||||
// vim: ts=4 sw=4 et
|
||||
|
||||
@@ -19,5 +19,6 @@ message FluxFileProto {
|
||||
optional int32 magic = 1;
|
||||
optional FluxFileVersion version = 2;
|
||||
repeated TrackFluxProto track = 3;
|
||||
optional double rotational_period_ms = 4;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "globals.h"
|
||||
#include "fluxmap.h"
|
||||
#include "decoders/fluxmapreader.h"
|
||||
#include "protocol.h"
|
||||
|
||||
Fluxmap& Fluxmap::appendBytes(const Bytes& bytes)
|
||||
@@ -62,39 +63,6 @@ Fluxmap& Fluxmap::appendDesync()
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Fluxmap::precompensate(int threshold_ticks, int amount_ticks)
|
||||
{
|
||||
uint8_t junk = 0xff;
|
||||
|
||||
for (unsigned i = 0; i < _bytes.size(); i++)
|
||||
{
|
||||
uint8_t& prev = (i == 0) ? junk : _bytes[i - 1];
|
||||
uint8_t prevticks = prev & 0x3f;
|
||||
uint8_t currticks = _bytes[i] & 0x3f;
|
||||
|
||||
if (currticks < (3 * threshold_ticks))
|
||||
{
|
||||
if ((prevticks <= threshold_ticks) && (currticks > threshold_ticks))
|
||||
{
|
||||
/* 01001; move the previous bit backwards. */
|
||||
if (prevticks >= (1 + amount_ticks))
|
||||
prev -= amount_ticks;
|
||||
if (currticks <= (0x7f - amount_ticks))
|
||||
currticks += amount_ticks;
|
||||
}
|
||||
else if ((prevticks > threshold_ticks) &&
|
||||
(currticks <= threshold_ticks))
|
||||
{
|
||||
/* 00101; move the current bit forwards. */
|
||||
if (prevticks <= (0x7f - amount_ticks))
|
||||
prev += amount_ticks;
|
||||
if (currticks >= (1 + amount_ticks))
|
||||
currticks -= amount_ticks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<const Fluxmap>> Fluxmap::split() const
|
||||
{
|
||||
std::vector<std::unique_ptr<const Fluxmap>> maps;
|
||||
@@ -108,24 +76,3 @@ std::vector<std::unique_ptr<const Fluxmap>> Fluxmap::split() const
|
||||
|
||||
return maps;
|
||||
}
|
||||
|
||||
std::unique_ptr<const Fluxmap> Fluxmap::rescale(double scale) const
|
||||
{
|
||||
if (scale == 1.0)
|
||||
return std::make_unique<Fluxmap>(rawBytes());
|
||||
|
||||
auto newFluxmap = std::make_unique<Fluxmap>();
|
||||
int lastEvent = 0;
|
||||
for (uint8_t b : _bytes)
|
||||
{
|
||||
lastEvent += b & 0x3f;
|
||||
if (b & 0xc0)
|
||||
{
|
||||
newFluxmap->appendInterval(lastEvent * scale + 0.5);
|
||||
newFluxmap->findLastByte() |= b & 0xc0;
|
||||
lastEvent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return newFluxmap;
|
||||
}
|
||||
|
||||
@@ -64,9 +64,8 @@ public:
|
||||
|
||||
Fluxmap& appendBits(const std::vector<bool>& bits, nanoseconds_t clock);
|
||||
|
||||
void precompensate(int threshold_ticks, int amount_ticks);
|
||||
std::unique_ptr<const Fluxmap> precompensate(int threshold_ticks, int amount_ticks);
|
||||
std::vector<std::unique_ptr<const Fluxmap>> split() const;
|
||||
std::unique_ptr<const Fluxmap> rescale(double scale) const;
|
||||
|
||||
private:
|
||||
uint8_t& findLastByte();
|
||||
|
||||
@@ -24,7 +24,6 @@ message Fl2FluxSinkProto {
|
||||
}
|
||||
|
||||
message FluxSinkProto {
|
||||
optional double rescale = 7 [ default = 1.0, (help) = "amount to multiply pulse periods by" ];
|
||||
oneof dest {
|
||||
HardwareFluxSinkProto drive = 2;
|
||||
AuFluxSinkProto au = 3;
|
||||
|
||||
@@ -16,22 +16,27 @@ public:
|
||||
{
|
||||
if (config.drive().has_hard_sector_count())
|
||||
{
|
||||
nanoseconds_t oneRevolution;
|
||||
int retries = 5;
|
||||
usbSetDrive(config.drive().drive(), config.drive().high_density(), config.drive().index_mode());
|
||||
Logger() << BeginSpeedOperationLogMessage();
|
||||
|
||||
do {
|
||||
oneRevolution = usbGetRotationalPeriod(config.drive().hard_sector_count());
|
||||
_hardSectorThreshold = oneRevolution * 3 / (4 * config.drive().hard_sector_count());
|
||||
retries--;
|
||||
} while ((oneRevolution == 0) && (retries > 0));
|
||||
nanoseconds_t oneRevolution = config.drive().rotational_period_ms() * 1e6;
|
||||
if (oneRevolution == 0)
|
||||
{
|
||||
Logger() << BeginSpeedOperationLogMessage();
|
||||
|
||||
do {
|
||||
oneRevolution = usbGetRotationalPeriod(config.drive().hard_sector_count());
|
||||
_hardSectorThreshold = oneRevolution * 3 / (4 * config.drive().hard_sector_count());
|
||||
retries--;
|
||||
} while ((oneRevolution == 0) && (retries > 0));
|
||||
config.mutable_drive()->set_rotational_period_ms(oneRevolution / 1e6);
|
||||
|
||||
Logger() << EndSpeedOperationLogMessage { oneRevolution };
|
||||
}
|
||||
|
||||
if (oneRevolution == 0) {
|
||||
Error() << "Failed\nIs a disk in the drive?";
|
||||
}
|
||||
|
||||
Logger() << EndSpeedOperationLogMessage { oneRevolution };
|
||||
}
|
||||
else
|
||||
_hardSectorThreshold = 0;
|
||||
|
||||
@@ -31,7 +31,6 @@ message Fl2FluxSourceProto {
|
||||
}
|
||||
|
||||
message FluxSourceProto {
|
||||
optional double rescale = 9 [ default = 1.0, (help) = "amount to divide pulse periods by" ];
|
||||
oneof source {
|
||||
HardwareFluxSourceProto drive = 2;
|
||||
TestPatternFluxSourceProto test_pattern = 3;
|
||||
|
||||
@@ -54,18 +54,23 @@ public:
|
||||
usbSetDrive(config.drive().drive(), config.drive().high_density(), config.drive().index_mode());
|
||||
Logger() << BeginSpeedOperationLogMessage();
|
||||
|
||||
do
|
||||
{
|
||||
_oneRevolution =
|
||||
usbGetRotationalPeriod(config.drive().hard_sector_count());
|
||||
if (config.drive().hard_sector_count() != 0)
|
||||
_hardSectorThreshold =
|
||||
_oneRevolution * 3 / (4 * config.drive().hard_sector_count());
|
||||
else
|
||||
_hardSectorThreshold = 0;
|
||||
_oneRevolution = config.drive().rotational_period_ms() * 1e6;
|
||||
if (_oneRevolution == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
_oneRevolution =
|
||||
usbGetRotationalPeriod(config.drive().hard_sector_count());
|
||||
if (config.drive().hard_sector_count() != 0)
|
||||
_hardSectorThreshold =
|
||||
_oneRevolution * 3 / (4 * config.drive().hard_sector_count());
|
||||
else
|
||||
_hardSectorThreshold = 0;
|
||||
|
||||
retries--;
|
||||
} while ((_oneRevolution == 0) && (retries > 0));
|
||||
retries--;
|
||||
} while ((_oneRevolution == 0) && (retries > 0));
|
||||
config.mutable_drive()->set_rotational_period_ms(_oneRevolution / 1e6);
|
||||
}
|
||||
|
||||
if (_oneRevolution == 0)
|
||||
Error() << "Failed\nIs a disk in the drive?";
|
||||
|
||||
@@ -97,8 +97,8 @@ public:
|
||||
int trackMfm = -1;
|
||||
|
||||
auto trackdata = ibm->add_trackdata();
|
||||
trackdata->set_clock_rate_khz(clockRate);
|
||||
trackdata->set_track_length_ms(167);
|
||||
trackdata->set_target_clock_period_us(1e3 / clockRate);
|
||||
trackdata->set_target_rotational_period_ms(167);
|
||||
auto sectors = trackdata->mutable_sectors();
|
||||
|
||||
for (int sectorInTrack = 0; sectorInTrack < currentSectorsInTrack;
|
||||
@@ -193,8 +193,8 @@ public:
|
||||
if (mediaFlag != 0x20)
|
||||
{
|
||||
auto trackdata = ibm->add_trackdata();
|
||||
trackdata->set_clock_rate_khz(clockRate);
|
||||
trackdata->set_track_length_ms(167);
|
||||
trackdata->set_target_clock_period_us(1e3 / clockRate);
|
||||
trackdata->set_target_rotational_period_ms(167);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
{
|
||||
auto ibm = config.mutable_encoder()->mutable_ibm();
|
||||
auto trackdata = ibm->add_trackdata();
|
||||
trackdata->set_clock_rate_khz(500);
|
||||
trackdata->set_target_clock_period_us(2);
|
||||
auto sectors = trackdata->mutable_sectors();
|
||||
switch (mediaByte)
|
||||
{
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
Logger() << "DIM: automatically setting format to 1.2MB "
|
||||
"(1024 byte sectors)";
|
||||
config.mutable_tracks()->set_end(76);
|
||||
trackdata->set_track_length_ms(167);
|
||||
trackdata->set_target_rotational_period_ms(167);
|
||||
trackdata->set_sector_size(1024);
|
||||
for (int i = 0; i < 9; i++)
|
||||
sectors->add_sector(i);
|
||||
@@ -118,14 +118,14 @@ public:
|
||||
case 0x02:
|
||||
Logger() << "DIM: automatically setting format to 1.2MB "
|
||||
"(512 byte sectors)";
|
||||
trackdata->set_track_length_ms(167);
|
||||
trackdata->set_target_rotational_period_ms(167);
|
||||
trackdata->set_sector_size(512);
|
||||
for (int i = 0; i < 15; i++)
|
||||
sectors->add_sector(i);
|
||||
break;
|
||||
case 0x03:
|
||||
Logger() << "DIM: automatically setting format to 1.44MB";
|
||||
trackdata->set_track_length_ms(200);
|
||||
trackdata->set_target_rotational_period_ms(200);
|
||||
trackdata->set_sector_size(512);
|
||||
for (int i = 0; i < 18; i++)
|
||||
sectors->add_sector(i);
|
||||
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
{
|
||||
auto ibm = config.mutable_encoder()->mutable_ibm();
|
||||
auto trackdata = ibm->add_trackdata();
|
||||
trackdata->set_clock_rate_khz(500);
|
||||
trackdata->set_target_clock_period_us(2);
|
||||
auto sectors = trackdata->mutable_sectors();
|
||||
switch (fddType)
|
||||
{
|
||||
@@ -90,14 +90,14 @@ public:
|
||||
Logger() << "FDI: automatically setting format to 1.2MB "
|
||||
"(1024 byte sectors)";
|
||||
config.mutable_tracks()->set_end(76);
|
||||
trackdata->set_track_length_ms(167);
|
||||
trackdata->set_target_rotational_period_ms(167);
|
||||
trackdata->set_sector_size(1024);
|
||||
for (int i = 0; i < 9; i++)
|
||||
sectors->add_sector(i);
|
||||
break;
|
||||
case 0x30:
|
||||
Logger() << "FDI: automatically setting format to 1.44MB";
|
||||
trackdata->set_track_length_ms(200);
|
||||
trackdata->set_target_rotational_period_ms(200);
|
||||
trackdata->set_sector_size(512);
|
||||
for (int i = 0; i < 18; i++)
|
||||
sectors->add_sector(i);
|
||||
|
||||
@@ -65,8 +65,8 @@ public:
|
||||
for (int track = 0; track < 163; track++)
|
||||
{
|
||||
auto trackdata = ibm->add_trackdata();
|
||||
trackdata->set_clock_rate_khz(500);
|
||||
trackdata->set_track_length_ms(167);
|
||||
trackdata->set_target_clock_period_us(2);
|
||||
trackdata->set_target_rotational_period_ms(167);
|
||||
auto sectors = trackdata->mutable_sectors();
|
||||
int currentTrackTrack = -1;
|
||||
int currentTrackHead = -1;
|
||||
|
||||
@@ -78,16 +78,27 @@ std::string Logger::toString(const AnyLogMessage& message)
|
||||
[&](const TrackReadLogMessage& m)
|
||||
{
|
||||
const auto& track = *m.track;
|
||||
const auto& trackdataflux = track.trackDatas.end()[-1];
|
||||
|
||||
std::set<std::shared_ptr<const Sector>> rawSectors;
|
||||
std::set<std::shared_ptr<const Record>> rawRecords;
|
||||
for (const auto& trackDataFlux : track.trackDatas)
|
||||
{
|
||||
rawSectors.insert(trackDataFlux->sectors.begin(), trackDataFlux->sectors.end());
|
||||
rawRecords.insert(trackDataFlux->records.begin(), trackDataFlux->records.end());
|
||||
}
|
||||
|
||||
nanoseconds_t clock = 0;
|
||||
for (const auto& sector : rawSectors)
|
||||
clock += sector->clock;
|
||||
if (!rawSectors.empty())
|
||||
clock /= rawSectors.size();
|
||||
|
||||
indent();
|
||||
stream << fmt::format("{} raw records, {} raw sectors",
|
||||
trackdataflux->records.size(),
|
||||
trackdataflux->sectors.size());
|
||||
if (trackdataflux->sectors.size() > 0)
|
||||
rawRecords.size(),
|
||||
rawSectors.size());
|
||||
if (clock != 0)
|
||||
{
|
||||
nanoseconds_t clock =
|
||||
(*trackdataflux->sectors.begin())->clock;
|
||||
stream << fmt::format("; {:.2f}us clock ({:.0f}kHz)",
|
||||
clock / 1000.0,
|
||||
1000000.0 / clock);
|
||||
@@ -104,7 +115,9 @@ std::string Logger::toString(const AnyLogMessage& message)
|
||||
sectors.begin(), sectors.end(), sectorPointerSortPredicate);
|
||||
|
||||
for (const auto& sector : sectors)
|
||||
stream << fmt::format(" {}{}",
|
||||
stream << fmt::format(" {}.{}.{}{}",
|
||||
sector->logicalTrack,
|
||||
sector->logicalSide,
|
||||
sector->logicalSector,
|
||||
Sector::statusToChar(sector->status));
|
||||
|
||||
@@ -119,18 +132,6 @@ std::string Logger::toString(const AnyLogMessage& message)
|
||||
size += sector->data.size();
|
||||
}
|
||||
|
||||
if (!track_ids.empty())
|
||||
{
|
||||
std::vector<std::string> ids;
|
||||
|
||||
for (const auto& i : track_ids)
|
||||
ids.push_back(fmt::format("{}.{}", i.first, i.second));
|
||||
|
||||
indent();
|
||||
stream << fmt::format(
|
||||
"logical track {}\n", fmt::join(ids, "; "));
|
||||
}
|
||||
|
||||
indent();
|
||||
stream << fmt::format("{} bytes decoded\n", size);
|
||||
},
|
||||
|
||||
@@ -107,14 +107,13 @@ std::unique_ptr<const Image> Mapper::remapSectorsLogicalToPhysical(
|
||||
|
||||
unsigned Mapper::remapTrackPhysicalToLogical(unsigned ptrack)
|
||||
{
|
||||
return (ptrack - config.drive().head_bias()) /
|
||||
config.drive().head_width();
|
||||
return (ptrack - config.drive().head_bias()) / config.drive().head_width();
|
||||
}
|
||||
|
||||
static unsigned getTrackStep()
|
||||
{
|
||||
unsigned track_step =
|
||||
(config.tpi() == 0) ? 1 : (config.drive().tpi() / config.tpi());
|
||||
(config.tpi() == 0) ? 1 : (config.drive().tpi() / config.tpi());
|
||||
|
||||
if (track_step == 0)
|
||||
Error()
|
||||
@@ -124,7 +123,7 @@ static unsigned getTrackStep()
|
||||
|
||||
unsigned Mapper::remapTrackLogicalToPhysical(unsigned ltrack)
|
||||
{
|
||||
return config.drive().head_bias() + ltrack*getTrackStep();
|
||||
return config.drive().head_bias() + ltrack * getTrackStep();
|
||||
}
|
||||
|
||||
std::set<Location> Mapper::computeLocations()
|
||||
@@ -136,7 +135,8 @@ std::set<Location> Mapper::computeLocations()
|
||||
{
|
||||
for (unsigned head : iterate(config.heads()))
|
||||
{
|
||||
unsigned physicalTrack = config.drive().head_bias() + logicalTrack * track_step;
|
||||
unsigned physicalTrack =
|
||||
config.drive().head_bias() + logicalTrack * track_step;
|
||||
|
||||
locations.insert({.physicalTrack = physicalTrack,
|
||||
.logicalTrack = logicalTrack,
|
||||
@@ -147,3 +147,15 @@ std::set<Location> Mapper::computeLocations()
|
||||
|
||||
return locations;
|
||||
}
|
||||
|
||||
nanoseconds_t Mapper::calculatePhysicalClockPeriod(
|
||||
nanoseconds_t targetClockPeriod, nanoseconds_t targetRotationalPeriod)
|
||||
{
|
||||
nanoseconds_t currentRotationalPeriod =
|
||||
config.drive().rotational_period_ms() * 1e6;
|
||||
if (currentRotationalPeriod == 0)
|
||||
Error() << "you must set --drive.rotational_period_ms as it can't be "
|
||||
"autodetected";
|
||||
|
||||
return targetClockPeriod * (currentRotationalPeriod / targetRotationalPeriod);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,10 @@ public:
|
||||
static unsigned remapTrackPhysicalToLogical(unsigned track);
|
||||
static unsigned remapTrackLogicalToPhysical(unsigned track);
|
||||
|
||||
static std::set<Location> computeLocations();
|
||||
static std::set<Location> computeLocations();
|
||||
|
||||
static nanoseconds_t calculatePhysicalClockPeriod(
|
||||
nanoseconds_t targetClockPeriod, nanoseconds_t targetRotationalPeriod);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -153,9 +153,9 @@ ReadResult readGroup(FluxSourceIteratorHolder& fluxSourceIteratorHolder,
|
||||
|
||||
Logger() << BeginReadOperationLogMessage{
|
||||
location.physicalTrack + offset, location.head};
|
||||
std::shared_ptr<const Fluxmap> fluxmap =
|
||||
fluxSourceIterator.next()->rescale(
|
||||
1.0 / config.flux_source().rescale());
|
||||
std::shared_ptr<const Fluxmap> fluxmap = fluxSourceIterator.next();
|
||||
// ->rescale(
|
||||
// 1.0 / config.flux_source().rescale());
|
||||
Logger() << EndReadOperationLogMessage()
|
||||
<< fmt::format("{0:.0} ms in {1} bytes",
|
||||
fluxmap->duration() / 1e6,
|
||||
@@ -186,8 +186,8 @@ void writeTracks(FluxSink& fluxSink,
|
||||
int retriesRemaining = config.decoder().retries();
|
||||
for (;;)
|
||||
{
|
||||
for (unsigned offset = 0; offset < location.groupSize;
|
||||
offset += config.drive().head_width())
|
||||
for (int offset = location.groupSize - 1; offset >= 0;
|
||||
offset -= config.drive().head_width())
|
||||
{
|
||||
unsigned physicalTrack = location.physicalTrack + offset;
|
||||
|
||||
@@ -200,13 +200,7 @@ void writeTracks(FluxSink& fluxSink,
|
||||
if (!fluxmap)
|
||||
goto erase;
|
||||
|
||||
auto scaled =
|
||||
fluxmap->rescale(config.flux_sink().rescale());
|
||||
/* Precompensation actually seems to make things worse, so
|
||||
* let's leave it disabled for now. */
|
||||
// fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS,
|
||||
// 2);
|
||||
fluxSink.writeFlux(physicalTrack, location.head, *scaled);
|
||||
fluxSink.writeFlux(physicalTrack, location.head, *fluxmap);
|
||||
Logger() << fmt::format("writing {0} ms in {1} bytes",
|
||||
int(fluxmap->duration() / 1e6),
|
||||
fluxmap->bytes());
|
||||
@@ -273,9 +267,16 @@ void writeTracksAndVerify(FluxSink& fluxSink,
|
||||
auto trackFlux = std::make_shared<TrackFlux>();
|
||||
trackFlux->location = location;
|
||||
FluxSourceIteratorHolder fluxSourceIteratorHolder(fluxSource);
|
||||
readGroup(fluxSourceIteratorHolder, location, *trackFlux, decoder);
|
||||
auto result = readGroup(
|
||||
fluxSourceIteratorHolder, location, *trackFlux, decoder);
|
||||
Logger() << TrackReadLogMessage{trackFlux};
|
||||
|
||||
if (result != GOOD_READ)
|
||||
{
|
||||
Logger() << "bad read";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto wantedSectors = encoder.collectSectors(location, image);
|
||||
std::sort(wantedSectors.begin(),
|
||||
wantedSectors.end(),
|
||||
@@ -287,11 +288,16 @@ void writeTracksAndVerify(FluxSink& fluxSink,
|
||||
gotSectors.end(),
|
||||
sectorPointerSortPredicate);
|
||||
|
||||
return std::equal(gotSectors.begin(),
|
||||
gotSectors.end(),
|
||||
wantedSectors.begin(),
|
||||
wantedSectors.end(),
|
||||
sectorPointerEqualsPredicate);
|
||||
if (!std::equal(gotSectors.begin(),
|
||||
gotSectors.end(),
|
||||
wantedSectors.begin(),
|
||||
wantedSectors.end(),
|
||||
sectorPointerEqualsPredicate))
|
||||
{
|
||||
Logger() << "good read but the data doesn't match";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -475,8 +481,7 @@ void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink)
|
||||
auto fluxSourceIterator = fluxsource.readFlux(track, head);
|
||||
|
||||
Logger() << BeginReadOperationLogMessage{track, head};
|
||||
auto fluxmap = fluxSourceIterator->next()->rescale(
|
||||
1.0 / config.flux_source().rescale());
|
||||
auto fluxmap = fluxSourceIterator->next();
|
||||
Logger() << EndReadOperationLogMessage()
|
||||
<< fmt::format("{0:.0} ms in {1} bytes",
|
||||
fluxmap->duration() / 1e6,
|
||||
|
||||
Reference in New Issue
Block a user