Skip to content

Commit

Permalink
WIP: Add solved/reconstructed fluxmap support.
Browse files Browse the repository at this point in the history
This proof of concept adds an optional encoder and fluxsink that
runs after the image is written.

This currently exposes the config of the solvedEncoder, though I
think I ultimately don't want it to be exposed as part of the
config proto.

Another way to do this would be by extending the decoders and/or
directly reading their records. That is actually closer to what I
want in many ways, however those records would need to be
deduplicated from multiple reads, etc.

The ultimate goal is to exactly replicate the timing of the
original sectors, but with a stable clock, sectors reread if a
bad read happens, and garbage between sectors removed. This
requires extending the sector struct to have more information
than it currently holds.
  • Loading branch information
tdaede committed Aug 12, 2022
1 parent e733dc9 commit 5af2218
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 4 deletions.
30 changes: 30 additions & 0 deletions arch/ibm/encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,33 @@ std::unique_ptr<AbstractEncoder> createIbmEncoder(const EncoderProto& config)
{
return std::unique_ptr<AbstractEncoder>(new IbmEncoder(config));
}

std::unique_ptr<AbstractEncoder> createIbmEncoderFromImage(EncoderProto& config, const Image& image)
{
IbmEncoderProto* ibm;
Geometry geometry;
ibm = config.mutable_ibm();
geometry = image.getGeometry();
std::map<int,std::map<int,std::vector<const Sector*>>> tracks_heads;
for (const auto& sector : image) {
tracks_heads[sector->logicalTrack][sector->logicalSide].push_back(sector.get());
}
for (const auto& track: tracks_heads) {
for (const auto& head : track.second) {
auto trackdata = ibm->mutable_trackdata()->Add();
for (const auto& sector : head.second) {
trackdata->mutable_sectors()->mutable_sector()->Add(sector->logicalSector);
trackdata->set_sector_size(sector->data.size());
// note: this currently only uses the last sector's parameters
trackdata->set_target_clock_period_us(sector->clock / 1000.0 * 2.0);
}
trackdata->set_track(track.first);
trackdata->set_head(head.first);
trackdata->set_gap0(0x1b);
trackdata->set_gap2(0x09);
trackdata->set_gap3(0x1b);
trackdata->set_target_rotational_period_ms(167);
}
}
return createIbmEncoder(config);
}
1 change: 1 addition & 0 deletions arch/ibm/ibm.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ class EncoderProto;

extern std::unique_ptr<AbstractDecoder> createIbmDecoder(const DecoderProto& config);
extern std::unique_ptr<AbstractEncoder> createIbmEncoder(const EncoderProto& config);
extern std::unique_ptr<AbstractEncoder> createIbmEncoderFromImage(EncoderProto& config, const Image& image);

#endif
4 changes: 3 additions & 1 deletion lib/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import "lib/drive.proto";
import "lib/mapper.proto";
import "lib/common.proto";

// NEXT_TAG: 17
// NEXT_TAG: 19
message ConfigProto {
optional string comment = 8;
optional bool is_extension = 13;
Expand All @@ -21,9 +21,11 @@ message ConfigProto {

optional FluxSourceProto flux_source = 10;
optional FluxSinkProto flux_sink = 11;
optional FluxSinkProto solved_flux = 17;
optional DriveProto drive = 15;

optional EncoderProto encoder = 3;
optional EncoderProto solved_encoder = 18;
optional DecoderProto decoder = 4;
optional UsbProto usb = 5;

Expand Down
18 changes: 18 additions & 0 deletions lib/encoders/encoders.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "arch/tids990/tids990.h"
#include "arch/victor9k/victor9k.h"
#include "lib/encoders/encoders.pb.h"
#include "lib/decoders/decoders.pb.h"
#include "lib/image.h"
#include "protocol.h"

std::unique_ptr<AbstractEncoder> AbstractEncoder::create(
Expand Down Expand Up @@ -40,6 +42,22 @@ std::unique_ptr<AbstractEncoder> AbstractEncoder::create(
return (encoder->second)(config);
}

std::unique_ptr<AbstractEncoder> AbstractEncoder::createFromImage(EncoderProto& encoderConfig,
const DecoderProto& decoderConfig, const Image& image)
{
static const std::map<int,
std::function<std::unique_ptr<AbstractEncoder>(EncoderProto&, const Image&)>>
encoders = {
{DecoderProto::kIbm, createIbmEncoderFromImage},
};

auto encoder = encoders.find(decoderConfig.format_case());
if (encoder == encoders.end())
Error() << "solved fluxmaps not supported for this format";

return (encoder->second)(encoderConfig, image);
}

Fluxmap& Fluxmap::appendBits(const std::vector<bool>& bits, nanoseconds_t clock)
{
nanoseconds_t now = duration();
Expand Down
3 changes: 3 additions & 0 deletions lib/encoders/encoders.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define ENCODERS_H

class EncoderProto;
class DecoderProto;
class Fluxmap;
class Image;
class Location;
Expand All @@ -14,6 +15,8 @@ class AbstractEncoder
virtual ~AbstractEncoder() {}

static std::unique_ptr<AbstractEncoder> create(const EncoderProto& config);
static std::unique_ptr<AbstractEncoder> createFromImage(EncoderProto& encoderConfig,
const DecoderProto& decoderConfig, const Image& image);

public:
virtual std::vector<std::shared_ptr<const Sector>> collectSectors(
Expand Down
7 changes: 6 additions & 1 deletion lib/readerwriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -470,14 +470,19 @@ std::shared_ptr<const DiskFlux> readDiskCommand(
}

void readDiskCommand(
FluxSource& fluxsource, AbstractDecoder& decoder, ImageWriter& writer)
FluxSource& fluxsource, AbstractDecoder& decoder, ImageWriter& writer,FluxSink* solvedFlux)
{
auto diskflux = readDiskCommand(fluxsource, decoder);

writer.printMap(*diskflux->image);
if (config.decoder().has_write_csv_to())
writer.writeCsv(*diskflux->image, config.decoder().write_csv_to());
writer.writeImage(*diskflux->image);
if (config.has_solved_flux()) {
std::unique_ptr<AbstractEncoder> solvedEncoder = AbstractEncoder::createFromImage(*config.mutable_encoder(),
config.decoder(), *diskflux->image);
writeTracks(*solvedFlux, *solvedEncoder, *diskflux->image);
}
}

void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink)
Expand Down
2 changes: 1 addition & 1 deletion lib/readerwriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extern std::unique_ptr<TrackDataFlux> readAndDecodeTrack(
FluxSource& source, AbstractDecoder& decoder, unsigned track, unsigned head);

extern std::shared_ptr<const DiskFlux> readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder);
extern void readDiskCommand(FluxSource& source, AbstractDecoder& decoder, ImageWriter& writer);
extern void readDiskCommand(FluxSource& source, AbstractDecoder& decoder, ImageWriter& writer, FluxSink* solvedFlux);
extern void rawReadDiskCommand(FluxSource& source, FluxSink& sink);

#endif
16 changes: 15 additions & 1 deletion src/fe-read.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "readerwriter.h"
#include "fluxmap.h"
#include "decoders/decoders.h"
#include "encoders/encoders.h"
#include "macintosh/macintosh.h"
#include "sector.h"
#include "proto.h"
Expand Down Expand Up @@ -45,6 +46,15 @@ static StringFlag copyFluxTo(
FluxSink::updateConfigForFilename(config.mutable_decoder()->mutable_copy_flux_to(), value);
});

static StringFlag solvedFlux(
{ "-r", "--solved" },
"after reading, write a reconstructed/solved fluxmap to this file",
"",
[](const auto& value)
{
FluxSink::updateConfigForFilename(config.mutable_solved_flux(), value);
});

static StringFlag srcTracks(
{ "--cylinders", "-c" },
"tracks to read from",
Expand Down Expand Up @@ -76,8 +86,12 @@ int mainRead(int argc, const char* argv[])
std::unique_ptr<FluxSource> fluxSource(FluxSource::create(config.flux_source()));
std::unique_ptr<AbstractDecoder> decoder(AbstractDecoder::create(config.decoder()));
std::unique_ptr<ImageWriter> writer(ImageWriter::create(config.image_writer()));
std::unique_ptr<FluxSink> solvedFlux;
std::unique_ptr<AbstractEncoder> solvedEncoder;
if (config.has_solved_flux()) {
solvedFlux = FluxSink::create(config.solved_flux()); }

readDiskCommand(*fluxSource, *decoder, *writer);
readDiskCommand(*fluxSource, *decoder, *writer, solvedFlux.get());

return 0;
}
Expand Down

0 comments on commit 5af2218

Please sign in to comment.