Skip to content

Commit

Permalink
Refactor the write code to make it easier to add new encoders.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidgiven committed Aug 6, 2019
1 parent 973f4c2 commit 5748f01
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 93 deletions.
11 changes: 7 additions & 4 deletions lib/brother/brother.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#define BROTHER_DATA_RECORD_CHECKSUM 3
#define BROTHER_DATA_RECORD_ENCODED_SIZE 415

#define BROTHER_TRACKS_PER_DISK 78
#define BROTHER_SECTORS_PER_TRACK 12

class Sector;
class Fluxmap;

Expand All @@ -26,11 +29,11 @@ class BrotherEncoder : public AbstractEncoder
{
public:
virtual ~BrotherEncoder() {}

public:
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
};

extern void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor,
int track, int sector);
extern void writeBrotherSectorData(std::vector<bool>& bits, unsigned& cursor,
const Bytes& data);
extern FlagGroup brotherEncoderFlags;

#endif
78 changes: 76 additions & 2 deletions lib/brother/encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,35 @@
#include "encoders/encoders.h"
#include "brother.h"
#include "crc.h"
#include "sectorset.h"
#include "writer.h"

FlagGroup brotherEncoderFlags;

static DoubleFlag clockRateUs(
{ "--clock-rate" },
"Encoded data clock rate (microseconds).",
3.83);

static DoubleFlag postIndexGapMs(
{ "--post-index-gap" },
"Post-index gap before first sector header (milliseconds).",
1.0);

static DoubleFlag sectorSpacingMs(
{ "--sector-spacing" },
"Time between successive sector headers (milliseconds).",
16.2);

static DoubleFlag postHeaderSpacingMs(
{ "--post-header-spacing" },
"Time between a sector's header and data records (milliseconds).",
0.69);

static StringFlag sectorSkew(
{ "--sector-skew" },
"Order in which to write sectors.",
"05a3816b4927");

static int encode_header_gcr(uint16_t word)
{
Expand Down Expand Up @@ -41,7 +70,7 @@ static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint32_t data,
}
}

void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor,
static void write_sector_header(std::vector<bool>& bits, unsigned& cursor,
int track, int sector)
{
write_bits(bits, cursor, 0xffffffff, 31);
Expand All @@ -51,7 +80,7 @@ void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor,
write_bits(bits, cursor, encode_header_gcr(0x2f), 16);
}

void writeBrotherSectorData(std::vector<bool>& bits, unsigned& cursor, const Bytes& data)
static void write_sector_data(std::vector<bool>& bits, unsigned& cursor, const Bytes& data)
{
write_bits(bits, cursor, 0xffffffff, 32);
write_bits(bits, cursor, BROTHER_DATA_RECORD, 32);
Expand Down Expand Up @@ -90,4 +119,49 @@ void writeBrotherSectorData(std::vector<bool>& bits, unsigned& cursor, const Byt
write_byte(0);
}

static int charToInt(char c)
{
if (isdigit(c))
return c - '0';
return 10 + tolower(c) - 'a';
}

std::unique_ptr<Fluxmap> BrotherEncoder::encode(
int physicalTrack, int physicalSide, const SectorSet& allSectors)
{
if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_DISK)
|| (physicalSide != 0))
return std::unique_ptr<Fluxmap>();

int bitsPerRevolution = 200000.0 / clockRateUs;
const std::string& skew = sectorSkew.get();
std::vector<bool> bits(bitsPerRevolution);
unsigned cursor = 0;

for (int sectorCount=0; sectorCount<BROTHER_SECTORS_PER_TRACK; sectorCount++)
{
int sectorId = charToInt(skew.at(sectorCount));
double headerMs = postIndexGapMs + sectorCount*sectorSpacingMs;
unsigned headerCursor = headerMs*1e3 / clockRateUs;
double dataMs = headerMs + postHeaderSpacingMs;
unsigned dataCursor = dataMs*1e3 / clockRateUs;

const auto& sectorData = allSectors.get(physicalTrack, 0, sectorId);

fillBitmapTo(bits, cursor, headerCursor, { true, false });
write_sector_header(bits, cursor, physicalTrack, sectorId);
fillBitmapTo(bits, cursor, dataCursor, { true, false });
write_sector_data(bits, cursor, sectorData->data);
}

if (cursor > bits.size())
Error() << "track data overrun";
fillBitmapTo(bits, cursor, bits.size(), { true, false });

// The pre-index gap is not normally reported.
// std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl;

std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
fluxmap->appendBits(bits, clockRateUs*1e3);
return fluxmap;
}
13 changes: 12 additions & 1 deletion lib/encoders/encoders.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
#ifndef ENCODERS_H
#define ENCODERS_H

class AbstractEncoder {};
class Fluxmap;
class SectorSet;

class AbstractEncoder
{
public:
virtual ~AbstractEncoder() {}

public:
virtual std::unique_ptr<Fluxmap> encode(
int physicalTrack, int physicalSide, const SectorSet& allSectors) = 0;
};

#endif

22 changes: 21 additions & 1 deletion lib/writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
#include "protocol.h"
#include "usb.h"
#include "dataspec.h"
#include "encoders/encoders.h"
#include "fluxsource/fluxsource.h"
#include "fluxsink/fluxsink.h"
#include "fmt/format.h"
#include "record.h"
#include "image.h"
#include "sector.h"
#include "sectorset.h"

FlagGroup writerFlags { &hardwareFluxSourceFlags };

Expand Down Expand Up @@ -60,10 +65,12 @@ void writeTracks(
{
if (!outdb)
{
std::cout << "erasing" << std::endl;
std::cout << "erasing\n";
usbSeek(location.track);
usbErase(location.side);
}
else
std::cout << "skipping\n";
}
else
{
Expand Down Expand Up @@ -96,3 +103,16 @@ void fillBitmapTo(std::vector<bool>& bitmap,
}
}

void writeDiskCommand(
AbstractEncoder& encoder, const Geometry& geometry, const std::string& inputFilename)
{
SectorSet allSectors;

readSectorsFromFile(allSectors, geometry, inputFilename);
writeTracks(
[&](int track, int side) -> std::unique_ptr<Fluxmap>
{
return encoder.encode(track, side, allSectors);
}
);
}
4 changes: 4 additions & 0 deletions lib/writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
extern FlagGroup writerFlags;

class Fluxmap;
class AbstractEncoder;
class Geometry;

extern void setWriterDefaultDest(const std::string& dest);

Expand All @@ -15,5 +17,7 @@ extern void fillBitmapTo(std::vector<bool>& bitmap,
unsigned& cursor, unsigned terminateAt,
const std::vector<bool>& pattern);

extern void writeDiskCommand(
AbstractEncoder& encoder, const Geometry& geometry, const std::string& inputFilename);

#endif
89 changes: 4 additions & 85 deletions src/fe-writebrother.cc
Original file line number Diff line number Diff line change
@@ -1,109 +1,28 @@
#include "globals.h"
#include "flags.h"
#include "fluxmap.h"
#include "sector.h"
#include "sectorset.h"
#include "decoders/decoders.h"
#include "encoders/encoders.h"
#include "brother/brother.h"
#include "image.h"
#include "writer.h"
#include "fmt/format.h"
#include "image.h"
#include <fstream>
#include <ctype.h>

static FlagGroup flags { &writerFlags };
static FlagGroup flags { &writerFlags, &brotherEncoderFlags };

static StringFlag inputFilename(
{ "--input", "-i" },
"The input image file to read from.",
"brother.img");

static DoubleFlag clockRateUs(
{ "--clock-rate" },
"Encoded data clock rate (microseconds).",
3.83);

static DoubleFlag postIndexGapMs(
{ "--post-index-gap" },
"Post-index gap before first sector header (milliseconds).",
1.0);

static DoubleFlag sectorSpacingMs(
{ "--sector-spacing" },
"Time between successive sector headers (milliseconds).",
16.2);

static DoubleFlag postHeaderSpacingMs(
{ "--post-header-spacing" },
"Time between a sector's header and data records (milliseconds).",
0.69);


static StringFlag sectorSkew(
{ "--sector-skew" },
"Order in which to write sectors.",
"05a3816b4927");

static int charToInt(char c)
{
if (isdigit(c))
return c - '0';
return 10 + tolower(c) - 'a';
}

int mainWriteBrother(int argc, const char* argv[])
{
setWriterDefaultDest(":d=0:t=0-77:s=0");
flags.parseFlags(argc, argv);

SectorSet allSectors;
BrotherEncoder encoder;
Geometry geometry = {78, 1, 12, 256};
readSectorsFromFile(allSectors, geometry, inputFilename);

int bitsPerRevolution = 200000.0 / clockRateUs;
std::cerr << bitsPerRevolution << " bits per 200ms revolution" << std::endl
<< fmt::format("post-index gap: {:.3f}ms\n", (double)postIndexGapMs);

const std::string& skew = sectorSkew;

writeTracks(
[&](int track, int side) -> std::unique_ptr<Fluxmap>
{
if ((track < 0) || (track > 77) || (side != 0))
return std::unique_ptr<Fluxmap>();

std::vector<bool> bits(bitsPerRevolution);
unsigned cursor = 0;

for (int sectorCount=0; sectorCount<geometry.sectors; sectorCount++)
{
int sectorId = charToInt(skew.at(sectorCount));
double headerMs = postIndexGapMs + sectorCount*sectorSpacingMs;
unsigned headerCursor = headerMs*1e3 / clockRateUs;
double dataMs = headerMs + postHeaderSpacingMs;
unsigned dataCursor = dataMs*1e3 / clockRateUs;

auto& sectorData = allSectors.get(track, 0, sectorId);

fillBitmapTo(bits, cursor, headerCursor, { true, false });
writeBrotherSectorHeader(bits, cursor, track, sectorId);
fillBitmapTo(bits, cursor, dataCursor, { true, false });
writeBrotherSectorData(bits, cursor, sectorData->data);
}

if (cursor > bits.size())
Error() << "track data overrun";
fillBitmapTo(bits, cursor, bits.size(), { true, false });

// The pre-index gap is not normally reported.
// std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl;

std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
fluxmap->appendBits(bits, clockRateUs*1e3);
return fluxmap;
}
);
writeDiskCommand(encoder, geometry, inputFilename);

return 0;
}
Expand Down

0 comments on commit 5748f01

Please sign in to comment.