Rename FluxReader and FluxWriter to FluxSource and FluxSink.

This commit is contained in:
David Given
2019-04-16 21:07:58 +02:00
parent 0b937f5587
commit 3667595275
17 changed files with 133 additions and 133 deletions

View File

@@ -0,0 +1,26 @@
#include "globals.h"
#include "flags.h"
#include "dataspec.h"
#include "fluxsource.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<FluxSource> FluxSource::create(const DataSpec& spec)
{
const auto& filename = spec.filename;
if (filename.empty())
return createHardwareFluxSource(spec.drive);
else if (ends_with(filename, ".flux"))
return createSqliteFluxSource(filename);
else if (ends_with(filename, "/"))
return createStreamFluxSource(filename);
Error() << "unrecognised flux filename extension";
return std::unique_ptr<FluxSource>();
}

View File

@@ -0,0 +1,30 @@
#ifndef FLUXSOURCE_H
#define FLUXSOURCE_H
class Fluxmap;
class DataSpec;
class FluxSource
{
public:
virtual ~FluxSource() {}
private:
static std::unique_ptr<FluxSource> createSqliteFluxSource(const std::string& filename);
static std::unique_ptr<FluxSource> createHardwareFluxSource(unsigned drive);
static std::unique_ptr<FluxSource> createStreamFluxSource(const std::string& path);
public:
static std::unique_ptr<FluxSource> create(const DataSpec& spec);
public:
virtual std::unique_ptr<Fluxmap> readFlux(int track, int side) = 0;
virtual void recalibrate() {}
virtual bool retryable() { return false; }
};
extern void setHardwareFluxSourceRevolutions(int revolutions);
extern void setHardwareFluxSourceDensity(bool high_density);
#endif

View File

@@ -0,0 +1,68 @@
#include "globals.h"
#include "flags.h"
#include "fluxmap.h"
#include "usb.h"
#include "fluxsource.h"
static IntFlag revolutions(
{ "--revolutions" },
"read this many revolutions of the disk",
1);
static bool high_density = false;
void setHardwareFluxSourceDensity(bool high_density)
{
::high_density = high_density;
}
class HardwareFluxSource : public FluxSource
{
public:
HardwareFluxSource(unsigned drive):
_drive(drive)
{
}
~HardwareFluxSource()
{
}
public:
std::unique_ptr<Fluxmap> readFlux(int track, int side)
{
usbSetDrive(_drive, high_density);
usbSeek(track);
Bytes crunched = usbRead(side, revolutions);
auto fluxmap = std::make_unique<Fluxmap>();
fluxmap->appendBytes(crunched.uncrunch());
return fluxmap;
}
void recalibrate()
{
usbRecalibrate();
}
bool retryable()
{
return true;
}
private:
unsigned _drive;
unsigned _revolutions;
};
void setHardwareFluxSourceRevolutions(int revolutions)
{
::revolutions.value = ::revolutions.defaultValue = revolutions;
}
std::unique_ptr<FluxSource> FluxSource::createHardwareFluxSource(unsigned drive)
{
return std::unique_ptr<FluxSource>(new HardwareFluxSource(drive));
}

223
lib/fluxsource/kryoflux.cc Normal file
View File

@@ -0,0 +1,223 @@
#include "globals.h"
#include "fluxmap.h"
#include "kryoflux.h"
#include "protocol.h"
#include "fmt/format.h"
#include <fstream>
#include <glob.h>
#define MCLK_HZ (((18432000.0 * 73.0) / 14.0) / 2.0)
#define SCLK_HZ (MCLK_HZ / 2)
#define ICLK_HZ (MCLK_HZ / 16)
#define TICKS_PER_SCLK (TICK_FREQUENCY / SCLK_HZ)
std::unique_ptr<Fluxmap> readStream(const std::string& dir, unsigned track, unsigned side)
{
std::string suffix = fmt::format("{:02}.{}.raw", track, side);
std::string pattern = fmt::format("{}*{}", dir, suffix);
glob_t globdata;
if (glob(pattern.c_str(), GLOB_NOSORT, NULL, &globdata))
Error() << fmt::format("cannot access path '{}'", dir);
if (globdata.gl_pathc != 1)
Error() << fmt::format("data is ambiguous --- multiple files end in {}", suffix);
std::string filename = globdata.gl_pathv[0];
globfree(&globdata);
return readStream(filename);
}
std::unique_ptr<Fluxmap> readStream(const std::string& filename)
{
std::ifstream f(filename, std::ios::in | std::ios::binary);
if (!f.is_open())
Error() << fmt::format("cannot open input file '{}'", filename);
Bytes bytes;
ByteWriter bw(bytes);
bw.append(f);
return readStream(bytes);
}
std::unique_ptr<Fluxmap> readStream(const Bytes& bytes)
{
ByteReader br(bytes);
/* Pass 1: scan the stream looking for index marks. */
std::set<uint32_t> indexmarks;
br.seek(0);
while (!br.eof())
{
uint8_t b = br.read_8();
unsigned len = 0;
switch (b)
{
case 0x0d: /* OOB block */
{
int blocktype = br.read_8();
len = br.read_le16();
if (br.eof())
goto finished_pass_1;
if (blocktype == 0x02)
{
/* index data, sent asynchronously */
uint32_t streampos = br.read_le32();
indexmarks.insert(streampos);
len -= 4;
}
break;
}
default:
{
if ((b >= 0x00) && (b <= 0x07))
{
/* Flux2: double byte value */
len = 1;
}
else if (b == 0x08)
{
/* Nop1: do nothing */
len = 0;
}
else if (b == 0x09)
{
/* Nop2: skip one byte */
len = 1;
}
else if (b == 0x0a)
{
/* Nop3: skip two bytes */
len = 2;
}
else if (b == 0x0b)
{
/* Ovl16: the next block is 0x10000 sclks longer than normal. */
len = 0;
}
else if (b == 0x0c)
{
/* Flux3: triple byte value */
len = 2;
}
else if ((b >= 0x0e) && (b <= 0xff))
{
/* Flux1: single byte value */
len = 0;
}
else
Error() << fmt::format(
"unknown stream block byte 0x{:02x} at 0x{:08x}", b, (uint64_t)br.pos-1);
}
}
br.skip(len);
}
finished_pass_1:
/* Pass 2: actually read the data. */
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
int streamdelta = 0;
auto writeFlux = [&](uint32_t sclk)
{
const auto& nextindex = indexmarks.begin();
if (nextindex != indexmarks.end())
{
uint32_t nextindexpos = *nextindex + streamdelta;
if (br.pos >= nextindexpos)
{
fluxmap->appendIndex();
indexmarks.erase(nextindex);
}
}
int ticks = (double)sclk * TICKS_PER_SCLK;
fluxmap->appendInterval(ticks);
fluxmap->appendPulse();
};
uint32_t extrasclks = 0;
br.seek(0);
while (!br.eof())
{
unsigned b = br.read_8();
switch (b)
{
case 0x0d: /* OOB block */
{
int blocktype = br.read_8();
uint16_t blocklen = br.read_le16();
if (br.eof())
goto finished_pass_2;
switch (blocktype)
{
case 0x01: /* streaminfo */
{
uint32_t blockpos = br.pos - 3;
streamdelta = blockpos - br.read_le32();
blocklen -= 4;
break;
}
}
br.skip(blocklen);
break;
}
default:
{
if ((b >= 0x00) && (b <= 0x07))
{
/* Flux2: double byte value */
b = (b<<8) | br.read_8();
writeFlux(extrasclks + b);
extrasclks = 0;
}
else if (b == 0x08)
{
/* Nop1: do nothing */
}
else if (b == 0x09)
{
/* Nop2: skip one byte */
br.skip(1);
}
else if (b == 0x0a)
{
/* Nop3: skip two bytes */
br.skip(2);
}
else if (b == 0x0b)
{
/* Ovl16: the next block is 0x10000 sclks longer than normal. */
extrasclks += 0x10000;
}
else if (b == 0x0c)
{
/* Flux3: triple byte value */
int ticks = br.read_be16(); /* yes, really big-endian */
writeFlux(extrasclks + ticks);
extrasclks = 0;
}
else if ((b >= 0x0e) && (b <= 0xff))
{
/* Flux1: single byte value */
writeFlux(extrasclks + b);
extrasclks = 0;
}
else
Error() << fmt::format(
"unknown stream block byte 0x{:02x} at 0x{:08x}", b, (uint64_t)br.pos-1);
}
}
}
finished_pass_2:
if (!br.eof())
Error() << "I/O error reading stream";
return fluxmap;
}

View File

@@ -0,0 +1,8 @@
#ifndef STREAM_H
#define STREAM_H
extern std::unique_ptr<Fluxmap> readStream(const std::string& dir, unsigned track, unsigned side);
extern std::unique_ptr<Fluxmap> readStream(const std::string& path);
extern std::unique_ptr<Fluxmap> readStream(const Bytes& bytes);
#endif

View File

@@ -0,0 +1,42 @@
#include "globals.h"
#include "fluxmap.h"
#include "sql.h"
#include "fluxsource.h"
#include "fmt/format.h"
class SqliteFluxSource : public FluxSource
{
public:
SqliteFluxSource(const std::string& filename)
{
_indb = sqlOpen(filename, SQLITE_OPEN_READONLY);
int version = sqlGetVersion(_indb);
if (version != FLUX_VERSION_CURRENT)
Error() << fmt::format("that flux file is version {}, but this client is for version {}",
version, FLUX_VERSION_CURRENT);
}
~SqliteFluxSource()
{
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<FluxSource> FluxSource::createSqliteFluxSource(const std::string& filename)
{
return std::unique_ptr<FluxSource>(new SqliteFluxSource(filename));
}

View File

@@ -0,0 +1,33 @@
#include "globals.h"
#include "fluxmap.h"
#include "kryoflux.h"
#include "fluxsource.h"
class StreamFluxSource : public FluxSource
{
public:
StreamFluxSource(const std::string& path):
_path(path)
{
}
~StreamFluxSource()
{
}
public:
std::unique_ptr<Fluxmap> readFlux(int track, int side)
{
return readStream(_path, track, side);
}
void recalibrate() {}
private:
const std::string& _path;
};
std::unique_ptr<FluxSource> FluxSource::createStreamFluxSource(const std::string& path)
{
return std::unique_ptr<FluxSource>(new StreamFluxSource(path));
}