mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Refactor the low-level reading stuff to be cleaner, simpler, and allow more
flux sources.
This commit is contained in:
@@ -46,6 +46,7 @@ public:
|
||||
std::map<std::string, Modifier> modifiers;
|
||||
std::vector<Location> locations;
|
||||
unsigned drive;
|
||||
unsigned revolutions;
|
||||
};
|
||||
|
||||
std::ostream& operator << (std::ostream& os, const DataSpec& dataSpec)
|
||||
|
||||
24
lib/fluxreader/fluxreader.cc
Normal file
24
lib/fluxreader/fluxreader.cc
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "dataspec.h"
|
||||
#include "fluxreader.h"
|
||||
|
||||
static bool ends_with(const std::string& value, const std::string& ending)
|
||||
{
|
||||
if (ending.size() > value.size())
|
||||
return false;
|
||||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||
}
|
||||
|
||||
std::unique_ptr<FluxReader> FluxReader::create(const DataSpec& spec)
|
||||
{
|
||||
const auto& filename = spec.filename;
|
||||
|
||||
if (filename.empty())
|
||||
return createHardwareFluxReader(spec.drive);
|
||||
else if (ends_with(filename, ".flux"))
|
||||
return createSqliteFluxReader(filename);
|
||||
|
||||
Error() << "unrecognised flux filename extension";
|
||||
return std::unique_ptr<FluxReader>();
|
||||
}
|
||||
27
lib/fluxreader/fluxreader.h
Normal file
27
lib/fluxreader/fluxreader.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef FLUXREADER_H
|
||||
#define FLUXREADER_H
|
||||
|
||||
class Fluxmap;
|
||||
class DataSpec;
|
||||
|
||||
class FluxReader
|
||||
{
|
||||
public:
|
||||
virtual ~FluxReader() {}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<FluxReader> createSqliteFluxReader(const std::string& filename);
|
||||
static std::unique_ptr<FluxReader> createHardwareFluxReader(unsigned drive);
|
||||
|
||||
public:
|
||||
static std::unique_ptr<FluxReader> create(const DataSpec& spec);
|
||||
|
||||
public:
|
||||
virtual std::unique_ptr<Fluxmap> readFlux(int track, int side) = 0;
|
||||
virtual void recalibrate() {}
|
||||
};
|
||||
|
||||
extern void setHardwareFluxReaderRevolutions(int revolutions);
|
||||
|
||||
#endif
|
||||
|
||||
52
lib/fluxreader/hardwarefluxreader.cc
Normal file
52
lib/fluxreader/hardwarefluxreader.cc
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "fluxmap.h"
|
||||
#include "usb.h"
|
||||
#include "fluxreader.h"
|
||||
|
||||
static IntFlag revolutions(
|
||||
{ "--revolutions" },
|
||||
"read this many revolutions of the disk",
|
||||
1);
|
||||
|
||||
class HardwareFluxReader : public FluxReader
|
||||
{
|
||||
public:
|
||||
HardwareFluxReader(unsigned drive):
|
||||
_drive(drive)
|
||||
{
|
||||
}
|
||||
|
||||
~HardwareFluxReader()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
{
|
||||
usbSetDrive(_drive);
|
||||
usbSeek(track);
|
||||
return usbRead(side, revolutions);
|
||||
}
|
||||
|
||||
void recalibrate() {
|
||||
usbRecalibrate();
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned _drive;
|
||||
unsigned _revolutions;
|
||||
};
|
||||
|
||||
void setHardwareFluxReaderRevolutions(int revolutions)
|
||||
{
|
||||
::revolutions.value = ::revolutions.defaultValue = revolutions;
|
||||
}
|
||||
|
||||
std::unique_ptr<FluxReader> FluxReader::createHardwareFluxReader(unsigned drive)
|
||||
{
|
||||
return std::unique_ptr<FluxReader>(new HardwareFluxReader(drive));
|
||||
}
|
||||
|
||||
|
||||
|
||||
37
lib/fluxreader/sqlitefluxreader.cc
Normal file
37
lib/fluxreader/sqlitefluxreader.cc
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "globals.h"
|
||||
#include "fluxmap.h"
|
||||
#include "sql.h"
|
||||
#include "fluxreader.h"
|
||||
|
||||
class SqliteFluxReader : public FluxReader
|
||||
{
|
||||
public:
|
||||
SqliteFluxReader(const std::string& filename)
|
||||
{
|
||||
_indb = sqlOpen(filename, SQLITE_OPEN_READONLY);
|
||||
}
|
||||
|
||||
~SqliteFluxReader()
|
||||
{
|
||||
if (_indb)
|
||||
sqlClose(_indb);
|
||||
}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
{
|
||||
return sqlReadFlux(_indb, track, side);
|
||||
}
|
||||
|
||||
void recalibrate() {}
|
||||
|
||||
private:
|
||||
sqlite3* _indb;
|
||||
};
|
||||
|
||||
std::unique_ptr<FluxReader> FluxReader::createSqliteFluxReader(const std::string& filename)
|
||||
{
|
||||
return std::unique_ptr<FluxReader>(new SqliteFluxReader(filename));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "usb.h"
|
||||
#include "fluxreader.h"
|
||||
#include "reader.h"
|
||||
#include "fluxmap.h"
|
||||
#include "sql.h"
|
||||
@@ -22,15 +23,6 @@ static StringFlag destination(
|
||||
"write the raw magnetic flux to this file",
|
||||
"");
|
||||
|
||||
static SettableFlag justRead(
|
||||
{ "--just-read", "-R" },
|
||||
"just read the disk but do no further processing");
|
||||
|
||||
static IntFlag revolutions(
|
||||
{ "--revolutions" },
|
||||
"read this many revolutions of the disk",
|
||||
1);
|
||||
|
||||
static SettableFlag dumpRecords(
|
||||
{ "--dump-records" },
|
||||
"Dump the parsed records.");
|
||||
@@ -40,7 +32,6 @@ static IntFlag retries(
|
||||
"How many times to retry each track in the event of a read failure.",
|
||||
5);
|
||||
|
||||
static sqlite3* indb;
|
||||
static sqlite3* outdb;
|
||||
|
||||
void setReaderDefaultSource(const std::string& source)
|
||||
@@ -50,48 +41,21 @@ void setReaderDefaultSource(const std::string& source)
|
||||
|
||||
void setReaderRevolutions(int revolutions)
|
||||
{
|
||||
::revolutions.value = ::revolutions.defaultValue = revolutions;
|
||||
setHardwareFluxReaderRevolutions(revolutions);
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> ReaderTrack::read()
|
||||
std::unique_ptr<Fluxmap> Track::read()
|
||||
{
|
||||
std::cout << fmt::format("{0:>3}.{1}: ", track, side) << std::flush;
|
||||
std::unique_ptr<Fluxmap> fluxmap = reallyRead();
|
||||
std::cout << fmt::format(
|
||||
"{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl;
|
||||
|
||||
if (outdb)
|
||||
sqlWriteFlux(outdb, track, side, *fluxmap);
|
||||
|
||||
return fluxmap;
|
||||
std::cout << fmt::format("reading track {} side {}", track, side) << std::endl;
|
||||
return _fluxReader->readFlux(track, side);
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> CapturedReaderTrack::reallyRead()
|
||||
|
||||
void Track::recalibrate()
|
||||
{
|
||||
usbSetDrive(drive);
|
||||
usbSeek(track);
|
||||
return usbRead(side, revolutions);
|
||||
_fluxReader->recalibrate();
|
||||
}
|
||||
|
||||
void CapturedReaderTrack::recalibrate()
|
||||
{
|
||||
usbRecalibrate();
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> FileReaderTrack::reallyRead()
|
||||
{
|
||||
if (!indb)
|
||||
{
|
||||
indb = sqlOpen(source.value.filename, SQLITE_OPEN_READONLY);
|
||||
atexit([]() { sqlClose(indb); });
|
||||
}
|
||||
return sqlReadFlux(indb, track, side);
|
||||
}
|
||||
|
||||
void FileReaderTrack::recalibrate()
|
||||
{}
|
||||
|
||||
std::vector<std::unique_ptr<ReaderTrack>> readTracks()
|
||||
std::vector<std::unique_ptr<Track>> readTracks()
|
||||
{
|
||||
const DataSpec& dataSpec = source.value;
|
||||
|
||||
@@ -111,28 +75,14 @@ std::vector<std::unique_ptr<ReaderTrack>> readTracks()
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<ReaderTrack>> tracks;
|
||||
for (const auto& location : dataSpec.locations)
|
||||
{
|
||||
std::unique_ptr<ReaderTrack> t(
|
||||
dataSpec.filename.empty()
|
||||
? (ReaderTrack*)new CapturedReaderTrack()
|
||||
: (ReaderTrack*)new FileReaderTrack());
|
||||
t->drive = location.drive;
|
||||
t->track = location.track;
|
||||
t->side = location.side;
|
||||
tracks.push_back(std::move(t));
|
||||
}
|
||||
std::shared_ptr<FluxReader> fluxreader = FluxReader::create(dataSpec);
|
||||
|
||||
if (justRead)
|
||||
{
|
||||
for (auto& track : tracks)
|
||||
track->read();
|
||||
std::cout << "--just-read specified, terminating without further processing" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return tracks;
|
||||
std::vector<std::unique_ptr<Track>> tracks;
|
||||
for (const auto& location : dataSpec.locations)
|
||||
tracks.push_back(
|
||||
std::unique_ptr<Track>(new Track(fluxreader, location.track, location.side)));
|
||||
|
||||
return tracks;
|
||||
}
|
||||
|
||||
void readDiskCommand(
|
||||
@@ -141,12 +91,17 @@ void readDiskCommand(
|
||||
{
|
||||
bool failures = false;
|
||||
SectorSet allSectors;
|
||||
for (auto& track : readTracks())
|
||||
{
|
||||
for (const auto& track : readTracks())
|
||||
{
|
||||
std::map<int, std::unique_ptr<Sector>> readSectors;
|
||||
for (int retry = ::retries; retry >= 0; retry--)
|
||||
{
|
||||
std::cout << fmt::format("{0:>3}.{1}: ", track->track, track->side) << std::flush;
|
||||
std::unique_ptr<Fluxmap> fluxmap = track->read();
|
||||
std::cout << fmt::format(
|
||||
"{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl;
|
||||
if (outdb)
|
||||
sqlWriteFlux(outdb, track->track, track->side, *fluxmap);
|
||||
|
||||
nanoseconds_t clockPeriod = bitmapDecoder.guessClock(*fluxmap);
|
||||
std::cout << fmt::format(" {:.2f} us clock; ", (double)clockPeriod/1000.0) << std::flush;
|
||||
@@ -219,7 +174,7 @@ void readDiskCommand(
|
||||
{
|
||||
if (!printedTrack)
|
||||
{
|
||||
std::cout << "logical track " << sector->track << "; ";
|
||||
std::cout << fmt::format("logical track {}.{}; ", sector->track, sector->side);
|
||||
printedTrack = true;
|
||||
}
|
||||
|
||||
|
||||
52
lib/reader.h
52
lib/reader.h
@@ -2,40 +2,34 @@
|
||||
#define READER_H
|
||||
|
||||
class Fluxmap;
|
||||
class FluxReader;
|
||||
class BitmapDecoder;
|
||||
class RecordParser;
|
||||
|
||||
class ReaderTrack
|
||||
{
|
||||
public:
|
||||
virtual ~ReaderTrack() {}
|
||||
|
||||
int drive;
|
||||
int track;
|
||||
int side;
|
||||
|
||||
std::unique_ptr<Fluxmap> read();
|
||||
virtual std::unique_ptr<Fluxmap> reallyRead() = 0;
|
||||
virtual void recalibrate() = 0;
|
||||
};
|
||||
|
||||
class CapturedReaderTrack : public ReaderTrack
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> reallyRead();
|
||||
void recalibrate();
|
||||
};
|
||||
|
||||
class FileReaderTrack : public ReaderTrack
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> reallyRead();
|
||||
void recalibrate();
|
||||
};
|
||||
|
||||
extern void setReaderDefaultSource(const std::string& source);
|
||||
extern void setReaderRevolutions(int revolutions);
|
||||
extern std::vector<std::unique_ptr<ReaderTrack>> readTracks();
|
||||
|
||||
class Track
|
||||
{
|
||||
public:
|
||||
Track(std::shared_ptr<FluxReader>& fluxReader, unsigned track, unsigned side):
|
||||
track(track),
|
||||
side(side),
|
||||
_fluxReader(fluxReader)
|
||||
{}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> read();
|
||||
void recalibrate();
|
||||
|
||||
unsigned track;
|
||||
unsigned side;
|
||||
|
||||
private:
|
||||
std::shared_ptr<FluxReader> _fluxReader;
|
||||
};
|
||||
|
||||
extern std::vector<std::unique_ptr<Track>> readTracks();
|
||||
|
||||
extern void readDiskCommand(
|
||||
const BitmapDecoder& bitmapDecoder, const RecordParser& recordParser,
|
||||
|
||||
22
meson.build
22
meson.build
@@ -31,9 +31,21 @@ felib = shared_library('felib',
|
||||
feinc = include_directories('lib')
|
||||
|
||||
sqllib = shared_library('sqllib',
|
||||
['lib/sql.cc'],
|
||||
link_with: [felib],
|
||||
dependencies: [sqlite])
|
||||
['lib/sql.cc'],
|
||||
link_with: [felib],
|
||||
dependencies: [sqlite]
|
||||
)
|
||||
|
||||
fluxreaderlib = shared_library('fluxreaderlib',
|
||||
[
|
||||
'lib/fluxreader/fluxreader.cc',
|
||||
'lib/fluxreader/sqlitefluxreader.cc',
|
||||
'lib/fluxreader/hardwarefluxreader.cc',
|
||||
],
|
||||
include_directories: [feinc, fmtinc],
|
||||
link_with: [felib, sqllib, fmtlib]
|
||||
)
|
||||
fluxreaderinc = include_directories('lib/fluxreader')
|
||||
|
||||
decoderlib = shared_library('decoderlib',
|
||||
[
|
||||
@@ -49,8 +61,8 @@ decoderinc = include_directories('lib/decoders')
|
||||
|
||||
readerlib = shared_library('readerlib',
|
||||
['lib/reader.cc'],
|
||||
include_directories: [fmtinc, decoderinc],
|
||||
link_with: [felib, sqllib, fmtlib, decoderlib])
|
||||
include_directories: [fmtinc, decoderinc, fluxreaderinc],
|
||||
link_with: [felib, sqllib, fmtlib, decoderlib, fluxreaderlib])
|
||||
|
||||
writerlib = shared_library('writerlib',
|
||||
['lib/writer.cc'],
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "reader.h"
|
||||
#include "fluxmap.h"
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
|
||||
@@ -18,7 +18,7 @@ int main(int argc, const char* argv[])
|
||||
track->read();
|
||||
|
||||
writeTracks(
|
||||
[&](int physicalTrack, int physicalSide) -> std::unique_ptr<Fluxmap>
|
||||
[&](unsigned physicalTrack, unsigned physicalSide) -> std::unique_ptr<Fluxmap>
|
||||
{
|
||||
for (auto& track : tracks)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user