mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Refactor the write code to make it easier to add new encoders.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -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);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
extern FlagGroup writerFlags;
|
||||
|
||||
class Fluxmap;
|
||||
class AbstractEncoder;
|
||||
class Geometry;
|
||||
|
||||
extern void setWriterDefaultDest(const std::string& dest);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user