Begin generating the Brother bitstream and convert it to a fluxmap.

This commit is contained in:
David Given
2019-01-03 01:37:37 +01:00
parent d38952df2e
commit c564e6e14d
9 changed files with 151 additions and 14 deletions

View File

@@ -14,4 +14,7 @@ extern RecordVector decodeBitsToRecordsBrother(const std::vector<bool>& bitmap);
extern std::vector<std::unique_ptr<Sector>> parseRecordsToSectorsBrother(const RecordVector& records);
extern void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor,
int track, int sector);
#endif

36
lib/brother/encoder.cc Normal file
View File

@@ -0,0 +1,36 @@
#include "globals.h"
#include "record.h"
#include "brother.h"
static int encode_header_gcr(uint16_t word)
{
switch (word)
{
#define GCR_ENTRY(gcr, data) \
case data: return gcr;
#include "header_gcr.h"
#undef GCR_ENTRY
}
return -1;
};
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint32_t data, int width)
{
cursor += width;
for (int i=0; i<width; i++)
{
unsigned pos = cursor - i - 1;
if (pos < bits.size())
bits[pos] = data & 1;
data >>= 1;
}
}
void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor,
int track, int sector)
{
write_bits(bits, cursor, BROTHER_SECTOR_RECORD, 32);
write_bits(bits, cursor, encode_header_gcr(track), 16);
write_bits(bits, cursor, encode_header_gcr(sector), 16);
}

26
lib/encoder.cc Normal file
View File

@@ -0,0 +1,26 @@
#include "globals.h"
#include "fluxmap.h"
#include "protocol.h"
Fluxmap& Fluxmap::appendBits(const std::vector<bool>& bits, nanoseconds_t clock)
{
nanoseconds_t now = duration();
for (unsigned i=0; i<bits.size(); i++)
{
now += clock;
if (bits[i])
{
unsigned delta = (now - duration()) / NS_PER_TICK;
while (delta > 255)
{
appendIntervals({ 255 });
delta -= 255;
}
appendIntervals({ (uint8_t)delta });
}
}
return *this;
}

View File

@@ -2,7 +2,7 @@
#include "fluxmap.h"
#include "protocol.h"
Fluxmap& Fluxmap::appendIntervals(std::vector<uint8_t>& intervals)
Fluxmap& Fluxmap::appendIntervals(const std::vector<uint8_t>& intervals)
{
return appendIntervals(&intervals[0], intervals.size());
}

View File

@@ -19,12 +19,14 @@ public:
return NULL;
}
Fluxmap& appendIntervals(std::vector<uint8_t>& intervals);
Fluxmap& appendIntervals(const std::vector<uint8_t>& intervals);
Fluxmap& appendIntervals(const uint8_t* ptr, size_t len);
nanoseconds_t guessClock() const;
std::vector<bool> decodeToBits(nanoseconds_t clock_period) const;
Fluxmap& appendBits(const std::vector<bool>& bits, nanoseconds_t clock);
private:
nanoseconds_t _duration = 0;
int _ticks = 0;

34
lib/writer.cc Normal file
View File

@@ -0,0 +1,34 @@
#include "globals.h"
#include "flags.h"
#include "fluxmap.h"
#include "writer.h"
#include <regex>
static const std::regex DEST_REGEX("([^:]*)"
"(?::t=([0-9]+)(?:-([0-9]+))?)?"
"(?::s=([0-9]+)(?:-([0-9]+))?)?");
static StringFlag destination(
{ "--dest", "-d" },
"destination for data",
"");
void writeTrack(int track, int side, const Fluxmap& fluxmap)
{
Error() << "not implemented yet";
}
void fillBitmapTo(std::vector<bool>& bitmap,
unsigned& cursor, unsigned terminateAt,
const std::vector<bool>& pattern)
{
while (cursor < terminateAt)
{
for (bool b : pattern)
{
if (cursor < bitmap.size())
bitmap[cursor++] = b;
}
}
}

12
lib/writer.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef WRITER_H
#define WRITER_H
class Fluxmap;
extern void writeTrack(int track, int side, const Fluxmap& fluxmap);
extern void fillBitmapTo(std::vector<bool>& bitmap,
unsigned& cursor, unsigned terminateAt,
const std::vector<bool>& pattern);
#endif

View File

@@ -74,6 +74,7 @@ decoderinc = include_directories('lib/decoders')
encoderlib = shared_library('encoderlib',
[
'lib/encoder.cc',
],
include_directories: [feinc, fmtinc],
link_with: [felib, fmtlib]
@@ -101,6 +102,6 @@ executable('fe-seek', ['src/fe-seek.cc'], include_dire
executable('fe-testbulktransport', ['src/fe-testbulktransport.cc'], include_directories: [feinc], link_with: [felib])
executable('fe-readibm', ['src/fe-readibm.cc'], include_directories: [feinc, fmtinc, decoderinc], link_with: [felib, readerlib, decoderlib, fmtlib])
executable('fe-readbrother', ['src/fe-readbrother.cc'], include_directories: [feinc, fmtinc, decoderinc, brotherinc], link_with: [felib, readerlib, decoderlib, brotherdecoderlib, fmtlib])
executable('fe-writebrother', ['src/fe-writebrother.cc'], include_directories: [feinc, fmtinc, decoderinc, brotherinc], link_with: [felib, writerlib, decoderlib, brotherencoderlib, fmtlib])
executable('fe-writebrother', ['src/fe-writebrother.cc'], include_directories: [feinc, fmtinc, brotherinc], link_with: [felib, writerlib, encoderlib, brotherencoderlib, fmtlib])
executable('fe-inspect', ['src/fe-inspect.cc'], include_directories: [feinc, fmtinc, decoderinc], link_with: [felib, readerlib, decoderlib, fmtlib])

View File

@@ -7,8 +7,10 @@
#include "decoders.h"
#include "brother.h"
#include "image.h"
#include "writer.h"
#include <fmt/format.h>
#include <fstream>
#include <ctype.h>
static StringFlag inputFilename(
{ "--input", "-i" },
@@ -27,14 +29,27 @@ static IntFlag postIndexGapMs(
static DoubleFlag sectorSpacingMs(
{ "--sector-spacing" },
"Time between successive sector heads (milliseconds).",
"Time between successive sector headers (milliseconds).",
16.684);
static DoubleFlag postHeaderSpacingMs(
{ "--post-header-spacing" },
"Time between a sector's header and data records (milliseconds).",
0.694);
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 main(int argc, const char* argv[])
{
Flag::parseFlags(argc, argv);
@@ -43,28 +58,36 @@ int main(int argc, const char* argv[])
Geometry geometry = {78, 1, 12, 256};
readSectorsFromFile(allSectors, geometry, inputFilename);
double lastSectorAtMs = postIndexGapMs + geometry.sectors*sectorSpacingMs;
if (lastSectorAtMs > 200.0)
Error() << "with that spacing, some sectors won't fit in a track "
<< fmt::format("({:.3f}ms out of 200.0ms)", lastSectorAtMs);
int bitsPerRevolution = 200000.0 / clockRateUs;
std::cerr << bitsPerRevolution << " bits per 200ms revolution" << std::endl
<< fmt::format("post-index gap: {:.3f}ms\n", postIndexGapMs)
<< fmt::format("pre-index gap: {:.3f}ms\n", 200.0 - lastSectorAtMs);
<< fmt::format("post-index gap: {:.3f}ms\n", (double)postIndexGapMs);
const std::string& skew = sectorSkew;
for (int track=0; track<geometry.tracks; track++)
{
std::vector<bool> bits(bitsPerRevolution);
unsigned cursor = 0;
std::cerr << "logical track " << track << std::endl;
for (int sectorCount=0; sectorCount<geometry.sectors; sectorCount++)
{
int sectorId = skew.at(sectorCount) - '0';
double cursorMs = postIndexGapMs + sectorCount*sectorSpacingMs;
std::cerr << "logical sector " << sectorId << " at pos " << cursorMs << std::endl;
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;
fillBitmapTo(bits, cursor, headerCursor, { true, false });
writeBrotherSectorHeader(bits, cursor, track, sectorId);
fillBitmapTo(bits, cursor, dataCursor, { true, false });
if (cursor > bits.size())
Error() << "track data overrun";
}
Fluxmap fluxmap;
fluxmap.appendBits(bits, clockRateUs*1e3);
}
std::cerr << "Not implemented yet." << std::endl;