mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Convert scptoflux to a proper flux source.
This commit is contained in:
@@ -33,6 +33,9 @@ std::unique_ptr<FluxSource> FluxSource::create(const FluxSourceProto& config)
|
||||
|
||||
case FluxSourceProto::kTestPattern:
|
||||
return createTestPatternFluxSource(config.test_pattern());
|
||||
|
||||
case FluxSourceProto::kScp:
|
||||
return createScpFluxSource(config.scp());
|
||||
}
|
||||
|
||||
Error() << "bad input disk configuration";
|
||||
@@ -45,6 +48,7 @@ void FluxSource::updateConfigForFilename(const std::string& filename)
|
||||
static const std::vector<std::pair<std::regex, std::function<void(const std::string&)>>> formats =
|
||||
{
|
||||
{ std::regex("^(.*\\.flux)$"), [&](const auto& s) { f->set_fluxfile(s); }},
|
||||
{ std::regex("^(.*\\.scp)$"), [&](const auto& s) { f->mutable_scp()->set_filename(s); }},
|
||||
{ std::regex("^erase:$"), [&](const auto& s) { f->mutable_erase(); }},
|
||||
{ std::regex("^kryoflux:(.*)$"), [&](const auto& s) { f->mutable_kryoflux()->set_directory(s); }},
|
||||
{ std::regex("^testpattern:(.*)"), [&](const auto& s) { f->mutable_test_pattern(); }},
|
||||
|
||||
@@ -10,6 +10,7 @@ class HardwareFluxSourceProto;
|
||||
class TestPatternFluxSourceProto;
|
||||
class EraseFluxSourceProto;
|
||||
class KryofluxFluxSourceProto;
|
||||
class ScpFluxSourceProto;
|
||||
|
||||
class FluxSource
|
||||
{
|
||||
@@ -20,6 +21,7 @@ private:
|
||||
static std::unique_ptr<FluxSource> createSqliteFluxSource(const std::string& filename);
|
||||
static std::unique_ptr<FluxSource> createHardwareFluxSource(const HardwareFluxSourceProto& config);
|
||||
static std::unique_ptr<FluxSource> createKryofluxFluxSource(const KryofluxFluxSourceProto& config);
|
||||
static std::unique_ptr<FluxSource> createScpFluxSource(const ScpFluxSourceProto& config);
|
||||
static std::unique_ptr<FluxSource> createTestPatternFluxSource(const TestPatternFluxSourceProto& config);
|
||||
static std::unique_ptr<FluxSource> createEraseFluxSource(const EraseFluxSourceProto& config);
|
||||
|
||||
|
||||
@@ -24,6 +24,11 @@ message KryofluxFluxSourceProto {
|
||||
optional string directory = 1 [(help) = "path to Kryoflux stream directory"];
|
||||
}
|
||||
|
||||
message ScpFluxSourceProto {
|
||||
optional string filename = 1 [default = "flux.scp",
|
||||
(help) = ".scp file to read flux from"];
|
||||
}
|
||||
|
||||
message FluxSourceProto {
|
||||
oneof source {
|
||||
string fluxfile = 1;
|
||||
@@ -31,6 +36,7 @@ message FluxSourceProto {
|
||||
TestPatternFluxSourceProto test_pattern = 3;
|
||||
EraseFluxSourceProto erase = 4;
|
||||
KryofluxFluxSourceProto kryoflux = 5;
|
||||
ScpFluxSourceProto scp = 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
130
lib/fluxsource/scpfluxsource.cc
Normal file
130
lib/fluxsource/scpfluxsource.cc
Normal file
@@ -0,0 +1,130 @@
|
||||
#include "globals.h"
|
||||
#include "fluxmap.h"
|
||||
#include "kryoflux.h"
|
||||
#include "lib/fluxsource/fluxsource.pb.h"
|
||||
#include "fluxsource/fluxsource.h"
|
||||
#include "scp.h"
|
||||
#include "proto.h"
|
||||
#include "fmt/format.h"
|
||||
#include <fstream>
|
||||
|
||||
static int trackno(int strack)
|
||||
{
|
||||
return strack >> 1;
|
||||
}
|
||||
|
||||
static int headno(int strack)
|
||||
{
|
||||
return strack & 1;
|
||||
}
|
||||
|
||||
static int strackno(int track, int side)
|
||||
{
|
||||
return (track << 1) | side;
|
||||
}
|
||||
|
||||
class ScpFluxSource : public FluxSource
|
||||
{
|
||||
public:
|
||||
ScpFluxSource(const ScpFluxSourceProto& config):
|
||||
_config(config)
|
||||
{
|
||||
_if.open(_config.filename(), std::ios::in | std::ios::binary);
|
||||
if (!_if.is_open())
|
||||
Error() << fmt::format("cannot open input file '{}': {}", _config.filename(), strerror(errno));
|
||||
|
||||
_if.read((char*) &_header, sizeof(_header));
|
||||
check_for_error();
|
||||
|
||||
if ((_header.file_id[0] != 'S')
|
||||
|| (_header.file_id[1] != 'C')
|
||||
|| (_header.file_id[2] != 'P'))
|
||||
Error() << "input not a SCP file";
|
||||
|
||||
_resolution = 25 * (_header.resolution + 1);
|
||||
int startSide = (_header.heads == 2) ? 1 : 0;
|
||||
int endSide = (_header.heads == 1) ? 0 : 1;
|
||||
|
||||
if ((_header.cell_width != 0) && (_header.cell_width != 16))
|
||||
Error() << "currently only 16-bit cells in SCP files are supported";
|
||||
|
||||
std::cout << fmt::format("SCP tracks {}-{}, heads {}-{}\n",
|
||||
trackno(_header.start_track), trackno(_header.end_track), startSide, endSide);
|
||||
std::cout << fmt::format("SCP sample resolution: {} ns\n", _resolution);
|
||||
}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
{
|
||||
int strack = strackno(track, side);
|
||||
uint32_t offset = Bytes(_header.track[strack], 4).reader().read_le32();
|
||||
if (offset == 0)
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
|
||||
ScpTrack trackheader;
|
||||
_if.seekg(offset, std::ios::beg);
|
||||
_if.read((char*) &trackheader, sizeof(trackheader));
|
||||
check_for_error();
|
||||
|
||||
if ((trackheader.track_id[0] != 'T')
|
||||
|| (trackheader.track_id[1] != 'R')
|
||||
|| (trackheader.track_id[2] != 'K'))
|
||||
Error() << "corrupt SCP file";
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
nanoseconds_t pending = 0;
|
||||
unsigned inputBytes = 0;
|
||||
for (int revolution = 0; revolution < _header.revolutions; revolution++)
|
||||
{
|
||||
if (revolution != 0)
|
||||
fluxmap->appendIndex();
|
||||
|
||||
uint32_t datalength = Bytes(trackheader.revolution[revolution].length, 4).reader().read_le32();
|
||||
uint32_t dataoffset = Bytes(trackheader.revolution[revolution].offset, 4).reader().read_le32();
|
||||
|
||||
Bytes data(datalength*2);
|
||||
_if.seekg(dataoffset + offset, std::ios::beg);
|
||||
_if.read((char*) data.begin(), data.size());
|
||||
check_for_error();
|
||||
|
||||
ByteReader br(data);
|
||||
for (int cell = 0; cell < datalength; cell++)
|
||||
{
|
||||
uint16_t interval = br.read_be16();
|
||||
if (interval)
|
||||
{
|
||||
fluxmap->appendInterval((interval + pending) * _resolution / NS_PER_TICK);
|
||||
fluxmap->appendPulse();
|
||||
pending = 0;
|
||||
}
|
||||
else
|
||||
pending += 0x10000;
|
||||
}
|
||||
|
||||
inputBytes += datalength*2;
|
||||
}
|
||||
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
void recalibrate() {}
|
||||
|
||||
private:
|
||||
void check_for_error()
|
||||
{
|
||||
if (_if.fail())
|
||||
Error() << fmt::format("SCP read I/O error: {}", strerror(errno));
|
||||
}
|
||||
|
||||
private:
|
||||
const ScpFluxSourceProto& _config;
|
||||
std::ifstream _if;
|
||||
ScpHeader _header;
|
||||
nanoseconds_t _resolution;
|
||||
};
|
||||
|
||||
std::unique_ptr<FluxSource> FluxSource::createScpFluxSource(const ScpFluxSourceProto& config)
|
||||
{
|
||||
return std::unique_ptr<FluxSource>(new ScpFluxSource(config));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user