mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-24 11:11:02 -07:00
Refactor for better multi-read support. Each read is now held separately, with
F_DESYNC being deprecated, and FluxSource returns an iterator which can be used to retry reads.
This commit is contained in:
18
lib/bytes.cc
18
lib/bytes.cc
@@ -160,6 +160,24 @@ Bytes Bytes::slice(unsigned start) const
|
||||
return slice(start, len);
|
||||
}
|
||||
|
||||
std::vector<Bytes> Bytes::split(uint8_t separator) const
|
||||
{
|
||||
std::vector<Bytes> vector;
|
||||
|
||||
int lastEnd = 0;
|
||||
for (int i=0; i<size(); i++)
|
||||
{
|
||||
if ((*this)[i] == separator)
|
||||
{
|
||||
vector.push_back(this->slice(lastEnd, i-lastEnd));
|
||||
lastEnd = i + 1;
|
||||
}
|
||||
}
|
||||
vector.push_back(this->slice(lastEnd));
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
std::vector<bool> Bytes::toBits() const
|
||||
{
|
||||
std::vector<bool> bits;
|
||||
|
||||
@@ -51,6 +51,8 @@ public:
|
||||
Bytes& clear()
|
||||
{ resize(0); return *this; }
|
||||
|
||||
std::vector<Bytes> split(uint8_t separator) const;
|
||||
|
||||
Bytes slice(unsigned start, unsigned len) const;
|
||||
Bytes slice(unsigned start) const;
|
||||
Bytes swab() const;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
Fluxmap& Fluxmap::appendBytes(const Bytes& bytes)
|
||||
{
|
||||
if (bytes.size() == 0)
|
||||
return *this;
|
||||
if (bytes.size() == 0)
|
||||
return *this;
|
||||
|
||||
return appendBytes(&bytes[0], bytes.size());
|
||||
}
|
||||
@@ -18,7 +18,7 @@ Fluxmap& Fluxmap::appendBytes(const uint8_t* ptr, size_t len)
|
||||
while (len--)
|
||||
{
|
||||
uint8_t byte = *ptr++;
|
||||
_ticks += byte & 0x3f;
|
||||
_ticks += byte & 0x3f;
|
||||
bw.write_8(byte);
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ Fluxmap& Fluxmap::appendBytes(const uint8_t* ptr, size_t len)
|
||||
|
||||
uint8_t& Fluxmap::findLastByte()
|
||||
{
|
||||
if (_bytes.empty())
|
||||
appendByte(0x00);
|
||||
return *(_bytes.end() - 1);
|
||||
if (_bytes.empty())
|
||||
appendByte(0x00);
|
||||
return *(_bytes.end() - 1);
|
||||
}
|
||||
|
||||
Fluxmap& Fluxmap::appendInterval(uint32_t ticks)
|
||||
@@ -46,19 +46,19 @@ Fluxmap& Fluxmap::appendInterval(uint32_t ticks)
|
||||
|
||||
Fluxmap& Fluxmap::appendPulse()
|
||||
{
|
||||
findLastByte() |= 0x80;
|
||||
findLastByte() |= 0x80;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Fluxmap& Fluxmap::appendIndex()
|
||||
{
|
||||
findLastByte() |= 0x40;
|
||||
findLastByte() |= 0x40;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Fluxmap& Fluxmap::appendDesync()
|
||||
{
|
||||
appendByte(F_DESYNC);
|
||||
appendByte(F_DESYNC);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -66,65 +66,66 @@ void Fluxmap::precompensate(int threshold_ticks, int amount_ticks)
|
||||
{
|
||||
uint8_t junk = 0xff;
|
||||
|
||||
for (unsigned i=0; i<_bytes.size(); i++)
|
||||
for (unsigned i = 0; i < _bytes.size(); i++)
|
||||
{
|
||||
uint8_t& prev = (i == 0) ? junk : _bytes[i-1];
|
||||
uint8_t prevticks = prev & 0x3f;
|
||||
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 (currticks < (3 * threshold_ticks))
|
||||
{
|
||||
if ((prevticks <= threshold_ticks) && (currticks > threshold_ticks))
|
||||
{
|
||||
/* 01001; move the previous bit backwards. */
|
||||
if (prevticks >= (1+amount_ticks))
|
||||
if (prevticks >= (1 + amount_ticks))
|
||||
prev -= amount_ticks;
|
||||
if (currticks <= (0x7f-amount_ticks))
|
||||
if (currticks <= (0x7f - amount_ticks))
|
||||
currticks += amount_ticks;
|
||||
}
|
||||
else if ((prevticks > threshold_ticks) && (currticks <= threshold_ticks))
|
||||
else if ((prevticks > threshold_ticks) &&
|
||||
(currticks <= threshold_ticks))
|
||||
{
|
||||
/* 00101; move the current bit forwards. */
|
||||
if (prevticks <= (0x7f-amount_ticks))
|
||||
if (prevticks <= (0x7f - amount_ticks))
|
||||
prev += amount_ticks;
|
||||
if (currticks >= (1+amount_ticks))
|
||||
if (currticks >= (1 + amount_ticks))
|
||||
currticks -= amount_ticks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Fluxmap> Fluxmap::split() {
|
||||
std::vector<Fluxmap> maps;
|
||||
Fluxmap map;
|
||||
for (unsigned i=0; i<_bytes.size(); i++) {
|
||||
if (_bytes[i] == F_DESYNC) {
|
||||
if (i > 0)
|
||||
maps.push_back(map);
|
||||
map = Fluxmap();
|
||||
} else {
|
||||
map.appendByte(_bytes[i]);
|
||||
}
|
||||
std::vector<std::unique_ptr<const Fluxmap>> Fluxmap::split() const
|
||||
{
|
||||
std::vector<std::unique_ptr<const Fluxmap>> maps;
|
||||
auto bytesVector = rawBytes().split(F_DESYNC);
|
||||
|
||||
for (auto bytes : bytesVector)
|
||||
{
|
||||
if (bytes.size() != 0)
|
||||
maps.push_back(std::move(std::make_unique<Fluxmap>(bytes)));
|
||||
}
|
||||
maps.push_back(map);
|
||||
|
||||
return maps;
|
||||
}
|
||||
|
||||
void Fluxmap::rescale(double scale) {
|
||||
if (scale != 1.0) {
|
||||
auto bytesOrig = _bytes;
|
||||
_bytes = Bytes();
|
||||
_duration = 0;
|
||||
_ticks = 0;
|
||||
int lastEvent = 0;
|
||||
for (unsigned i=0; i<bytesOrig.size(); i++)
|
||||
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)
|
||||
{
|
||||
lastEvent += bytesOrig[i] & 0x3f;
|
||||
if (bytesOrig[i] & 0xc0) {
|
||||
appendInterval(lastEvent * scale + 0.5);
|
||||
findLastByte() |= bytesOrig[i] & 0xc0;
|
||||
lastEvent = 0;
|
||||
}
|
||||
newFluxmap->appendInterval(lastEvent * scale + 0.5);
|
||||
newFluxmap->findLastByte() |= b & 0xc0;
|
||||
lastEvent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return newFluxmap;
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ public:
|
||||
Fluxmap& appendBits(const std::vector<bool>& bits, nanoseconds_t clock);
|
||||
|
||||
void precompensate(int threshold_ticks, int amount_ticks);
|
||||
std::vector<Fluxmap> split();
|
||||
void rescale(double scale);
|
||||
std::vector<std::unique_ptr<const Fluxmap>> split() const;
|
||||
std::unique_ptr<const Fluxmap> rescale(double scale) const;
|
||||
|
||||
private:
|
||||
uint8_t& findLastByte();
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
void writeFlux(int cylinder, int head, Fluxmap& fluxmap)
|
||||
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
|
||||
{
|
||||
unsigned totalTicks = fluxmap.ticks() + 2;
|
||||
unsigned channels = _config.index_markers() ? 2 : 1;
|
||||
|
||||
@@ -39,7 +39,8 @@ public:
|
||||
auto track = proto.add_track();
|
||||
track->set_cylinder(e.first.first);
|
||||
track->set_head(e.first.second);
|
||||
track->set_flux(e.second);
|
||||
for (const auto& fluxBytes : e.second)
|
||||
track->add_flux(fluxBytes);
|
||||
}
|
||||
|
||||
if (!proto.SerializeToOstream(&_of))
|
||||
@@ -50,9 +51,10 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
void writeFlux(int cylinder, int head, Fluxmap& fluxmap)
|
||||
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
|
||||
{
|
||||
_data[std::make_pair(cylinder, head)] = fluxmap.rawBytes();
|
||||
auto& vector = _data[std::make_pair(cylinder, head)];
|
||||
vector.push_back(fluxmap.rawBytes());
|
||||
}
|
||||
|
||||
operator std::string () const
|
||||
@@ -63,7 +65,7 @@ public:
|
||||
private:
|
||||
std::string _filename;
|
||||
std::ofstream _of;
|
||||
std::map<std::pair<unsigned, unsigned>, Bytes> _data;
|
||||
std::map<std::pair<unsigned, unsigned>, std::vector<Bytes>> _data;
|
||||
};
|
||||
|
||||
std::unique_ptr<FluxSink> FluxSink::createFl2FluxSink(const Fl2FluxSinkProto& config)
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
static void updateConfigForFilename(FluxSinkProto* proto, const std::string& filename);
|
||||
|
||||
public:
|
||||
virtual void writeFlux(int track, int side, Fluxmap& fluxmap) = 0;
|
||||
virtual void writeFlux(int track, int side, const Fluxmap& fluxmap) = 0;
|
||||
|
||||
virtual operator std::string () const = 0;
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
void writeFlux(int track, int side, Fluxmap& fluxmap)
|
||||
void writeFlux(int track, int side, const Fluxmap& fluxmap) override
|
||||
{
|
||||
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
|
||||
#if 0
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "lib/fluxsink/fluxsink.pb.h"
|
||||
#include "proto.h"
|
||||
#include "fmt/format.h"
|
||||
#include "fluxmap.h"
|
||||
#include "scp.h"
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
@@ -79,7 +80,7 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
void writeFlux(int cylinder, int head, Fluxmap& fluxmap)
|
||||
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
|
||||
{
|
||||
ByteWriter trackdataWriter(_trackdata);
|
||||
trackdataWriter.seekToEnd();
|
||||
@@ -97,9 +98,7 @@ public:
|
||||
trackheader.header.track_id[2] = 'K';
|
||||
trackheader.header.strack = strack;
|
||||
|
||||
auto lastFluxmap = fluxmap.split().back();
|
||||
|
||||
FluxmapReader fmr(lastFluxmap);
|
||||
FluxmapReader fmr(fluxmap);
|
||||
Bytes fluxdata;
|
||||
ByteWriter fluxdataWriter(fluxdata);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
{}
|
||||
|
||||
public:
|
||||
void writeFlux(int cylinder, int head, Fluxmap& fluxmap)
|
||||
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
|
||||
{
|
||||
mkdir(_config.directory().c_str(), 0744);
|
||||
std::ofstream of(
|
||||
|
||||
@@ -30,7 +30,7 @@ struct CwfTrack
|
||||
uint8_t length[4]; // little-endian
|
||||
};
|
||||
|
||||
class CwfFluxSource : public FluxSource
|
||||
class CwfFluxSource : public TrivialFluxSource
|
||||
{
|
||||
public:
|
||||
CwfFluxSource(const CwfFluxSourceProto& config):
|
||||
@@ -79,11 +79,11 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side)
|
||||
{
|
||||
const auto& p = _trackOffsets.find(std::make_pair(track, side));
|
||||
if (p == _trackOffsets.end())
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
return std::make_unique<const Fluxmap>();
|
||||
|
||||
off_t pos = p->second.first;;
|
||||
size_t length = p->second.second;
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
#include "lib/fluxsource/fluxsource.pb.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
class EraseFluxSource : public FluxSource
|
||||
class EraseFluxSource : public TrivialFluxSource
|
||||
{
|
||||
public:
|
||||
EraseFluxSource(const EraseFluxSourceProto& config) {}
|
||||
~EraseFluxSource() {}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override
|
||||
{
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
return std::unique_ptr<const Fluxmap>();
|
||||
}
|
||||
|
||||
void recalibrate() {}
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
|
||||
std::unique_ptr<FluxSource> FluxSource::createEraseFluxSource(const EraseFluxSourceProto& config)
|
||||
{
|
||||
return std::unique_ptr<FluxSource>(new EraseFluxSource(config));
|
||||
return std::make_unique<EraseFluxSource>(config);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,46 @@
|
||||
#include "fluxsource/fluxsource.h"
|
||||
#include "proto.h"
|
||||
#include "fmt/format.h"
|
||||
#include "fluxmap.h"
|
||||
#include <fstream>
|
||||
|
||||
class Fl2FluxSourceIterator : public FluxSourceIterator
|
||||
{
|
||||
public:
|
||||
Fl2FluxSourceIterator(const TrackFluxProto& proto):
|
||||
_proto(proto)
|
||||
{}
|
||||
|
||||
bool hasNext() const override
|
||||
{
|
||||
return _count < _proto.flux_size();
|
||||
}
|
||||
|
||||
std::unique_ptr<const Fluxmap> next() override
|
||||
{
|
||||
auto bytes = _proto.flux(_count);
|
||||
_count++;
|
||||
return std::make_unique<Fluxmap>(bytes);
|
||||
}
|
||||
|
||||
private:
|
||||
const TrackFluxProto& _proto;
|
||||
int _count = 0;
|
||||
};
|
||||
|
||||
class EmptyFluxSourceIterator : public FluxSourceIterator
|
||||
{
|
||||
bool hasNext() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<const Fluxmap> next() override
|
||||
{
|
||||
Error() << "no flux to read";
|
||||
}
|
||||
};
|
||||
|
||||
class Fl2FluxSource : public FluxSource
|
||||
{
|
||||
public:
|
||||
@@ -24,15 +62,15 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int cylinder, int head)
|
||||
std::unique_ptr<FluxSourceIterator> readFlux(int cylinder, int head) override
|
||||
{
|
||||
for (const auto& track : _proto.track())
|
||||
{
|
||||
if ((track.cylinder() == cylinder) && (track.head() == head))
|
||||
return std::make_unique<Fluxmap>(track.flux());
|
||||
return std::make_unique<Fl2FluxSourceIterator>(track);
|
||||
}
|
||||
|
||||
return std::make_unique<Fluxmap>();
|
||||
return std::make_unique<EmptyFluxSourceIterator>();
|
||||
}
|
||||
|
||||
void recalibrate() {}
|
||||
@@ -51,14 +89,18 @@ private:
|
||||
/* Change a flux datastream with multiple segments separated by F_DESYNC into multiple
|
||||
* flux segments. */
|
||||
|
||||
for (auto* track = _proto.mutable_track())
|
||||
for (auto& track : *_proto.mutable_track())
|
||||
{
|
||||
Fluxmap old_flux(track.flux(0));
|
||||
auto split_flux = old_flux.split();
|
||||
if (track.flux_size() == 0)
|
||||
track.clear_flux();
|
||||
else
|
||||
{
|
||||
Fluxmap oldFlux(track.flux(0));
|
||||
|
||||
track.clear_flux();
|
||||
for (const auto& flux : split_flux)
|
||||
track.add_flux(flux.rawBytes());
|
||||
track.clear_flux();
|
||||
for (const auto& flux : oldFlux.split())
|
||||
track.add_flux(flux->rawBytes());
|
||||
}
|
||||
}
|
||||
|
||||
_proto.set_version(FluxFileVersion::VERSION_2);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "fluxsource/fluxsource.h"
|
||||
#include "fluxmap.h"
|
||||
#include "lib/config.pb.h"
|
||||
#include "proto.h"
|
||||
#include "utils.h"
|
||||
@@ -72,5 +73,36 @@ void FluxSource::updateConfigForFilename(FluxSourceProto* proto, const std::stri
|
||||
Error() << fmt::format("unrecognised flux filename '{}'", filename);
|
||||
}
|
||||
|
||||
class TrivialFluxSourceIterator : public FluxSourceIterator
|
||||
{
|
||||
public:
|
||||
TrivialFluxSourceIterator(TrivialFluxSource* fluxSource, int cylinder, int head):
|
||||
_fluxSource(fluxSource),
|
||||
_cylinder(cylinder),
|
||||
_head(head)
|
||||
{}
|
||||
|
||||
bool hasNext() const override
|
||||
{
|
||||
return !!_fluxSource;
|
||||
}
|
||||
|
||||
std::unique_ptr<const Fluxmap> next() override
|
||||
{
|
||||
auto fluxmap = _fluxSource->readSingleFlux(_cylinder, _head);
|
||||
_fluxSource = nullptr;
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
private:
|
||||
TrivialFluxSource* _fluxSource;
|
||||
int _cylinder;
|
||||
int _head;
|
||||
};
|
||||
|
||||
std::unique_ptr<FluxSourceIterator> TrivialFluxSource::readFlux(int cylinder, int head)
|
||||
{
|
||||
return std::make_unique<TrivialFluxSourceIterator>(this, cylinder, head);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,15 @@ class KryofluxFluxSourceProto;
|
||||
class ScpFluxSourceProto;
|
||||
class TestPatternFluxSourceProto;
|
||||
|
||||
class FluxSourceIterator
|
||||
{
|
||||
public:
|
||||
virtual ~FluxSourceIterator() {}
|
||||
|
||||
virtual bool hasNext() const = 0;
|
||||
virtual std::unique_ptr<const Fluxmap> next() = 0;
|
||||
};
|
||||
|
||||
class FluxSource
|
||||
{
|
||||
public:
|
||||
@@ -33,9 +42,16 @@ public:
|
||||
static void updateConfigForFilename(FluxSourceProto* proto, const std::string& filename);
|
||||
|
||||
public:
|
||||
virtual std::unique_ptr<Fluxmap> readFlux(int track, int side) = 0;
|
||||
virtual std::unique_ptr<FluxSourceIterator> readFlux(int track, int side) = 0;
|
||||
virtual void recalibrate() {}
|
||||
virtual bool retryable() { return false; }
|
||||
virtual bool isHardware() { return false; }
|
||||
};
|
||||
|
||||
class TrivialFluxSource : public FluxSource
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<FluxSourceIterator> readFlux(int track, int side);
|
||||
virtual std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,54 +9,87 @@
|
||||
|
||||
class HardwareFluxSource : public FluxSource
|
||||
{
|
||||
private:
|
||||
class HardwareFluxSourceIterator : public FluxSourceIterator
|
||||
{
|
||||
public:
|
||||
HardwareFluxSourceIterator(
|
||||
const HardwareFluxSource& fluxsource, int cylinder, int head):
|
||||
_fluxsource(fluxsource),
|
||||
_cylinder(cylinder),
|
||||
_head(head)
|
||||
{
|
||||
}
|
||||
|
||||
bool hasNext() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<const Fluxmap> next()
|
||||
{
|
||||
usbSetDrive(_fluxsource._config.drive(),
|
||||
_fluxsource._config.high_density(),
|
||||
_fluxsource._config.index_mode());
|
||||
usbSeek(_cylinder);
|
||||
|
||||
Bytes data = usbRead(_head,
|
||||
_fluxsource._config.sync_with_index(),
|
||||
_fluxsource._config.revolutions() * _fluxsource._oneRevolution,
|
||||
_fluxsource._hardSectorThreshold);
|
||||
auto fluxmap = std::make_unique<Fluxmap>();
|
||||
fluxmap->appendBytes(data);
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
private:
|
||||
const HardwareFluxSource& _fluxsource;
|
||||
int _cylinder;
|
||||
int _head;
|
||||
};
|
||||
|
||||
public:
|
||||
HardwareFluxSource(const HardwareFluxSourceProto& config):
|
||||
_config(config)
|
||||
HardwareFluxSource(const HardwareFluxSourceProto& config): _config(config)
|
||||
{
|
||||
int retries = 5;
|
||||
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
|
||||
Logger() << BeginSpeedOperationLogMessage();
|
||||
|
||||
do {
|
||||
_oneRevolution = usbGetRotationalPeriod(_config.hard_sector_count());
|
||||
usbSetDrive(
|
||||
_config.drive(), _config.high_density(), _config.index_mode());
|
||||
Logger() << BeginSpeedOperationLogMessage();
|
||||
|
||||
do
|
||||
{
|
||||
_oneRevolution =
|
||||
usbGetRotationalPeriod(_config.hard_sector_count());
|
||||
if (_config.hard_sector_count() != 0)
|
||||
_hardSectorThreshold = _oneRevolution * 3 / (4 * _config.hard_sector_count());
|
||||
_hardSectorThreshold =
|
||||
_oneRevolution * 3 / (4 * _config.hard_sector_count());
|
||||
else
|
||||
_hardSectorThreshold = 0;
|
||||
|
||||
retries--;
|
||||
} while ((_oneRevolution == 0) && (retries > 0));
|
||||
|
||||
if (_oneRevolution == 0) {
|
||||
Error() << "Failed\nIs a disk in the drive?";
|
||||
}
|
||||
if (_oneRevolution == 0)
|
||||
Error() << "Failed\nIs a disk in the drive?";
|
||||
|
||||
Logger() << EndSpeedOperationLogMessage { _oneRevolution };
|
||||
Logger() << EndSpeedOperationLogMessage{_oneRevolution};
|
||||
}
|
||||
|
||||
~HardwareFluxSource()
|
||||
{
|
||||
}
|
||||
~HardwareFluxSource() {}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
std::unique_ptr<FluxSourceIterator> readFlux(int cylinder, int head) override
|
||||
{
|
||||
usbSetDrive(_config.drive(), _config.high_density(), _config.index_mode());
|
||||
usbSeek(track);
|
||||
|
||||
Bytes data = usbRead(
|
||||
side, _config.sync_with_index(), _config.revolutions() * _oneRevolution, _hardSectorThreshold);
|
||||
auto fluxmap = std::make_unique<Fluxmap>();
|
||||
fluxmap->appendBytes(data);
|
||||
return fluxmap;
|
||||
return std::make_unique<HardwareFluxSourceIterator>(
|
||||
*this, cylinder, head);
|
||||
}
|
||||
|
||||
void recalibrate()
|
||||
void recalibrate() override
|
||||
{
|
||||
usbRecalibrate();
|
||||
}
|
||||
|
||||
bool retryable()
|
||||
bool isHardware() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -67,10 +100,8 @@ private:
|
||||
nanoseconds_t _hardSectorThreshold;
|
||||
};
|
||||
|
||||
std::unique_ptr<FluxSource> FluxSource::createHardwareFluxSource(const HardwareFluxSourceProto& config)
|
||||
std::unique_ptr<FluxSource> FluxSource::createHardwareFluxSource(
|
||||
const HardwareFluxSourceProto& config)
|
||||
{
|
||||
return std::unique_ptr<FluxSource>(new HardwareFluxSource(config));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "lib/fluxsource/fluxsource.pb.h"
|
||||
#include "fluxsource/fluxsource.h"
|
||||
|
||||
class KryofluxFluxSource : public FluxSource
|
||||
class KryofluxFluxSource : public TrivialFluxSource
|
||||
{
|
||||
public:
|
||||
KryofluxFluxSource(const KryofluxFluxSourceProto& config):
|
||||
@@ -12,7 +12,7 @@ public:
|
||||
{}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override
|
||||
{
|
||||
return readStream(_path, track, side);
|
||||
}
|
||||
@@ -25,5 +25,5 @@ private:
|
||||
|
||||
std::unique_ptr<FluxSource> FluxSource::createKryofluxFluxSource(const KryofluxFluxSourceProto& config)
|
||||
{
|
||||
return std::unique_ptr<FluxSource>(new KryofluxFluxSource(config));
|
||||
return std::make_unique<KryofluxFluxSource>(config);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ static int strackno(int track, int side)
|
||||
return (track << 1) | side;
|
||||
}
|
||||
|
||||
class ScpFluxSource : public FluxSource
|
||||
class ScpFluxSource : public TrivialFluxSource
|
||||
{
|
||||
public:
|
||||
ScpFluxSource(const ScpFluxSourceProto& config):
|
||||
@@ -55,14 +55,14 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override
|
||||
{
|
||||
int strack = strackno(track, side);
|
||||
if (strack >= ARRAY_SIZE(_header.track))
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
return std::make_unique<Fluxmap>();
|
||||
uint32_t offset = Bytes(_header.track[strack], 4).reader().read_le32();
|
||||
if (offset == 0)
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
return std::make_unique<Fluxmap>();
|
||||
|
||||
ScpTrackHeader trackheader;
|
||||
_if.seekg(offset, std::ios::beg);
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
revs[revolution] = trackrev;
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
auto fluxmap = std::make_unique<Fluxmap>();
|
||||
nanoseconds_t pending = 0;
|
||||
unsigned inputBytes = 0;
|
||||
for (int revolution = 0; revolution < _header.revolutions; revolution++)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "lib/fluxsource/fluxsource.pb.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
class TestPatternFluxSource : public FluxSource
|
||||
class TestPatternFluxSource : public TrivialFluxSource
|
||||
{
|
||||
public:
|
||||
TestPatternFluxSource(const TestPatternFluxSourceProto& config):
|
||||
@@ -14,9 +14,9 @@ public:
|
||||
~TestPatternFluxSource() {}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override
|
||||
{
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
auto fluxmap = std::make_unique<Fluxmap>();
|
||||
|
||||
while (fluxmap->duration() < (_config.sequence_length_us()*1000000.0))
|
||||
{
|
||||
@@ -35,7 +35,7 @@ private:
|
||||
|
||||
std::unique_ptr<FluxSource> FluxSource::createTestPatternFluxSource(const TestPatternFluxSourceProto& config)
|
||||
{
|
||||
return std::unique_ptr<FluxSource>(new TestPatternFluxSource(config));
|
||||
return std::make_unique<TestPatternFluxSource>(config);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,11 +22,10 @@
|
||||
|
||||
static std::unique_ptr<FluxSink> outputFluxSink;
|
||||
|
||||
static std::shared_ptr<Fluxmap> readFluxmap(FluxSource& fluxsource, unsigned cylinder, unsigned head)
|
||||
static std::shared_ptr<const Fluxmap> readFluxmap(FluxSourceIterator& fluxsourceIterator, unsigned cylinder, unsigned head)
|
||||
{
|
||||
Logger() << BeginReadOperationLogMessage { cylinder, head };
|
||||
std::shared_ptr<Fluxmap> fluxmap = fluxsource.readFlux(cylinder, head);
|
||||
fluxmap->rescale(1.0/config.flux_source().rescale());
|
||||
auto fluxmap = fluxsourceIterator.next()->rescale(1.0/config.flux_source().rescale());
|
||||
Logger() << EndReadOperationLogMessage()
|
||||
<< fmt::format("{0:.0} ms in {1} bytes", fluxmap->duration()/1e6, fluxmap->bytes());
|
||||
return fluxmap;
|
||||
@@ -107,9 +106,11 @@ std::shared_ptr<const DiskFlux> readDiskCommand(FluxSource& fluxsource, Abstract
|
||||
std::set<std::shared_ptr<const Record>> track_records;
|
||||
Fluxmap totalFlux;
|
||||
|
||||
for (int retry = config.decoder().retries(); retry >= 0; retry--)
|
||||
auto fluxsourceIterator = fluxsource.readFlux(cylinder, head);
|
||||
int retry = 0;
|
||||
while (fluxsourceIterator->hasNext())
|
||||
{
|
||||
auto fluxmap = readFluxmap(fluxsource, cylinder, head);
|
||||
auto fluxmap = readFluxmap(*fluxsourceIterator, cylinder, head);
|
||||
totalFlux.appendDesync().appendBytes(fluxmap->rawBytes());
|
||||
|
||||
auto trackdataflux =
|
||||
@@ -154,13 +155,17 @@ std::shared_ptr<const DiskFlux> readDiskCommand(FluxSource& fluxsource, Abstract
|
||||
if (!hasBadSectors)
|
||||
break;
|
||||
|
||||
if (!fluxsource.retryable())
|
||||
if (!fluxsourceIterator->hasNext())
|
||||
break;
|
||||
if (retry == 0)
|
||||
Logger() << fmt::format("giving up");
|
||||
else
|
||||
Logger()
|
||||
<< fmt::format("retrying; {} retries remaining", retry);
|
||||
if (fluxsource.isHardware())
|
||||
{
|
||||
retry++;
|
||||
if (retry == 0)
|
||||
Logger() << fmt::format("giving up");
|
||||
else
|
||||
Logger()
|
||||
<< fmt::format("retrying; {} retries remaining", retry);
|
||||
}
|
||||
}
|
||||
|
||||
if (outputFluxSink)
|
||||
@@ -232,7 +237,8 @@ void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink)
|
||||
for (int head : iterate(config.heads()))
|
||||
{
|
||||
testForEmergencyStop();
|
||||
auto fluxmap = readFluxmap(fluxsource, cylinder, head);
|
||||
auto fluxsourceIterator = fluxsource.readFlux(cylinder, head);
|
||||
auto fluxmap = readFluxmap(*fluxsourceIterator, cylinder, head);
|
||||
fluxsink.writeFlux(cylinder, head, *fluxmap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "proto.h"
|
||||
|
||||
void writeTracks(FluxSink& fluxSink,
|
||||
const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer)
|
||||
const std::function<std::unique_ptr<const Fluxmap>(int track, int side)> producer)
|
||||
{
|
||||
for (unsigned cylinder : iterate(config.cylinders()))
|
||||
{
|
||||
@@ -27,7 +27,7 @@ void writeTracks(FluxSink& fluxSink,
|
||||
testForEmergencyStop();
|
||||
Logger() << BeginWriteOperationLogMessage{cylinder, head};
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap = producer(cylinder, head);
|
||||
auto fluxmap = producer(cylinder, head);
|
||||
if (!fluxmap)
|
||||
{
|
||||
/* Erase this track rather than writing. */
|
||||
@@ -38,11 +38,11 @@ void writeTracks(FluxSink& fluxSink,
|
||||
}
|
||||
else
|
||||
{
|
||||
fluxmap->rescale(config.flux_sink().rescale());
|
||||
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(cylinder, head, *fluxmap);
|
||||
fluxSink.writeFlux(cylinder, head, *scaled);
|
||||
Logger() << fmt::format("{0} ms in {1} bytes",
|
||||
int(fluxmap->duration() / 1e6),
|
||||
fluxmap->bytes());
|
||||
@@ -99,8 +99,7 @@ void writeTracksAndVerify(FluxSink& fluxSink,
|
||||
fluxmap->bytes());
|
||||
|
||||
Logger() << BeginReadOperationLogMessage{cylinder, head};
|
||||
std::shared_ptr<Fluxmap> writtenFluxmap =
|
||||
fluxSource.readFlux(cylinder, head);
|
||||
std::shared_ptr<const Fluxmap> writtenFluxmap = fluxSource.readFlux(cylinder, head)->next();
|
||||
Logger() << EndReadOperationLogMessage()
|
||||
<< fmt::format("verifying {0} ms in {1} bytes",
|
||||
int(writtenFluxmap->duration() / 1e6),
|
||||
@@ -183,8 +182,8 @@ void writeDiskCommand(const Image& image,
|
||||
void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink)
|
||||
{
|
||||
writeTracks(fluxSink,
|
||||
[&](int track, int side) -> std::unique_ptr<Fluxmap>
|
||||
[&](int track, int side) -> std::unique_ptr<const Fluxmap>
|
||||
{
|
||||
return fluxSource.readFlux(track, side);
|
||||
return fluxSource.readFlux(track, side)->next();
|
||||
});
|
||||
}
|
||||
|
||||
18
lib/writer.h
18
lib/writer.h
@@ -9,14 +9,20 @@ class FluxSource;
|
||||
class FluxSink;
|
||||
class Image;
|
||||
|
||||
extern void writeTracks(FluxSink& fluxSink, const std::function<std::unique_ptr<Fluxmap>(int track, int side)> producer);
|
||||
extern void writeTracks(FluxSink& fluxSink,
|
||||
const std::function<std::unique_ptr<const Fluxmap>(int track, int side)>
|
||||
producer);
|
||||
|
||||
extern void fillBitmapTo(std::vector<bool>& bitmap,
|
||||
unsigned& cursor, unsigned terminateAt,
|
||||
const std::vector<bool>& pattern);
|
||||
|
||||
extern void writeDiskCommand(const Image& image, AbstractEncoder& encoder, FluxSink& fluxSink,
|
||||
AbstractDecoder* decoder = nullptr, FluxSource* fluxSource = nullptr);
|
||||
unsigned& cursor,
|
||||
unsigned terminateAt,
|
||||
const std::vector<bool>& pattern);
|
||||
|
||||
extern void writeDiskCommand(const Image& image,
|
||||
AbstractEncoder& encoder,
|
||||
FluxSink& fluxSink,
|
||||
AbstractDecoder* decoder = nullptr,
|
||||
FluxSource* fluxSource = nullptr);
|
||||
extern void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -89,7 +89,7 @@ enum
|
||||
{
|
||||
F_BIT_PULSE = 0x80,
|
||||
F_BIT_INDEX = 0x40,
|
||||
F_DESYNC = 0x00,
|
||||
F_DESYNC = 0x00, /* obsolete */
|
||||
F_EOF = 0x100 /* synthetic, only produced by library */
|
||||
};
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ int mainInspect(int argc, const char* argv[])
|
||||
flags.parseFlagsWithConfigFiles(argc, argv, {});
|
||||
|
||||
std::unique_ptr<FluxSource> fluxSource(FluxSource::create(config.flux_source()));
|
||||
const auto fluxmap = fluxSource->readFlux(cylinderFlag, headFlag);
|
||||
const auto fluxmap = fluxSource->readFlux(cylinderFlag, headFlag)->next();
|
||||
|
||||
std::cout << fmt::format("0x{:x} bytes of data in {:.3f}ms\n",
|
||||
fluxmap->bytes(),
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "globals.h"
|
||||
#include "bytes.h"
|
||||
#include "snowhouse/snowhouse.h"
|
||||
|
||||
using namespace snowhouse;
|
||||
|
||||
static void check_oob(Bytes& b, unsigned pos)
|
||||
{
|
||||
@@ -115,6 +118,49 @@ static void test_slice()
|
||||
assert((bs == Bytes{ 0, 0 }));
|
||||
}
|
||||
|
||||
static void test_split()
|
||||
{
|
||||
AssertThat(
|
||||
(Bytes{ }).split(0),
|
||||
Equals(std::vector<Bytes> {
|
||||
Bytes{}
|
||||
}));
|
||||
|
||||
AssertThat(
|
||||
(Bytes{ 0 }).split(0),
|
||||
Equals(std::vector<Bytes> {
|
||||
Bytes{},
|
||||
Bytes{}
|
||||
}));
|
||||
|
||||
AssertThat(
|
||||
(Bytes{ 1 }).split(0),
|
||||
Equals(std::vector<Bytes> {
|
||||
Bytes{ 1 }
|
||||
}));
|
||||
|
||||
AssertThat(
|
||||
(Bytes{ 1, 0 }).split(0),
|
||||
Equals(std::vector<Bytes> {
|
||||
Bytes{ 1 },
|
||||
Bytes{ }
|
||||
}));
|
||||
|
||||
AssertThat(
|
||||
(Bytes{ 0, 1 }).split(0),
|
||||
Equals(std::vector<Bytes> {
|
||||
Bytes{ },
|
||||
Bytes{ 1 }
|
||||
}));
|
||||
|
||||
AssertThat(
|
||||
(Bytes{ 1, 0, 1 }).split(0),
|
||||
Equals(std::vector<Bytes> {
|
||||
Bytes{ 1 },
|
||||
Bytes{ 1 }
|
||||
}));
|
||||
}
|
||||
|
||||
static void test_tobits()
|
||||
{
|
||||
Bytes b = {1, 2};
|
||||
@@ -139,6 +185,7 @@ int main(int argc, const char* argv[])
|
||||
test_reads();
|
||||
test_writes();
|
||||
test_slice();
|
||||
test_split();
|
||||
test_tobits();
|
||||
test_tostring();
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user