mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Make the DS990 encoder work, maybe?
This commit is contained in:
@@ -6,33 +6,54 @@
|
||||
#include "crc.h"
|
||||
#include "sectorset.h"
|
||||
#include "writer.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
FlagGroup tids990EncoderFlags;
|
||||
|
||||
static DoubleFlag clockRateUs(
|
||||
{ "--clock-rate" },
|
||||
"Encoded data clock rate (microseconds).",
|
||||
3.83);
|
||||
static IntFlag trackLengthMs(
|
||||
{ "--tids990-track-length-ms" },
|
||||
"Length of a track in milliseconds.",
|
||||
166);
|
||||
|
||||
static DoubleFlag postIndexGapMs(
|
||||
{ "--post-index-gap" },
|
||||
"Post-index gap before first sector header (milliseconds).",
|
||||
1.0);
|
||||
static IntFlag sectorCount(
|
||||
{ "--tids990-sector-count" },
|
||||
"Number of sectors per track.",
|
||||
26);
|
||||
|
||||
static DoubleFlag sectorSpacingMs(
|
||||
{ "--sector-spacing" },
|
||||
"Time between successive sector headers (milliseconds).",
|
||||
16.2);
|
||||
static IntFlag clockRateKhz(
|
||||
{ "--tids990-clock-rate-khz" },
|
||||
"Clock rate of data to write.",
|
||||
500);
|
||||
|
||||
static DoubleFlag postHeaderSpacingMs(
|
||||
{ "--post-header-spacing" },
|
||||
"Time between a sector's header and data records (milliseconds).",
|
||||
0.69);
|
||||
static HexIntFlag am1Byte(
|
||||
{ "--tids990-am1-byte" },
|
||||
"16-bit RAW bit pattern to use for the AM1 ID byte",
|
||||
0x2244);
|
||||
|
||||
static HexIntFlag am2Byte(
|
||||
{ "--tids990-am2-byte" },
|
||||
"16-bit RAW bit pattern to use for the AM2 ID byte",
|
||||
0x2245);
|
||||
|
||||
static IntFlag gap1(
|
||||
{ "--tids990-gap1-bytes" },
|
||||
"Size of gap 1 (the post-index gap).",
|
||||
80);
|
||||
|
||||
static IntFlag gap2(
|
||||
{ "--tids990-gap2-bytes" },
|
||||
"Size of gap 2 (the post-ID gap).",
|
||||
21);
|
||||
|
||||
static IntFlag gap3(
|
||||
{ "--tids990-gap3-bytes" },
|
||||
"Size of gap 3 (the post-data or format gap).",
|
||||
51);
|
||||
|
||||
static StringFlag sectorSkew(
|
||||
{ "--sector-skew" },
|
||||
"Order in which to write sectors.",
|
||||
"05a3816b4927");
|
||||
{ "--tids990-sector-skew" },
|
||||
"Order to emit sectors.",
|
||||
"1mhc72nid83oje94pkfa50lgb6");
|
||||
|
||||
static int charToInt(char c)
|
||||
{
|
||||
@@ -41,59 +62,115 @@ static int charToInt(char c)
|
||||
return 10 + tolower(c) - 'a';
|
||||
}
|
||||
|
||||
void TiDs990Encoder::writeRawBits(uint32_t data, int width)
|
||||
{
|
||||
_cursor += width;
|
||||
_lastBit = data & 1;
|
||||
for (int i=0; i<width; i++)
|
||||
{
|
||||
unsigned pos = _cursor - i - 1;
|
||||
if (pos < _bits.size())
|
||||
_bits[pos] = data & 1;
|
||||
data >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void TiDs990Encoder::writeBytes(const Bytes& bytes)
|
||||
{
|
||||
encodeMfm(_bits, _cursor, bytes, _lastBit);
|
||||
}
|
||||
|
||||
void TiDs990Encoder::writeBytes(int count, uint8_t byte)
|
||||
{
|
||||
Bytes bytes = { byte };
|
||||
for (int i=0; i<count; i++)
|
||||
writeBytes(bytes);
|
||||
}
|
||||
|
||||
static uint8_t decodeUint16(uint16_t raw)
|
||||
{
|
||||
Bytes b;
|
||||
ByteWriter bw(b);
|
||||
bw.write_be16(raw);
|
||||
return decodeFmMfm(b.toBits())[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> TiDs990Encoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
int logicalTrack;
|
||||
if (physicalSide != 0)
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
// physicalTrack -= _bias;
|
||||
// switch (_format)
|
||||
// {
|
||||
// case 120:
|
||||
// if ((physicalTrack < 0) || (physicalTrack >= (BROTHER_TRACKS_PER_120KB_DISK*2))
|
||||
// || (physicalTrack & 1))
|
||||
// return std::unique_ptr<Fluxmap>();
|
||||
// logicalTrack = physicalTrack/2;
|
||||
// break;
|
||||
//
|
||||
// case 240:
|
||||
// if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_240KB_DISK))
|
||||
// return std::unique_ptr<Fluxmap>();
|
||||
// logicalTrack = physicalTrack;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// 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(logicalTrack, 0, sectorId);
|
||||
//
|
||||
// fillBitmapTo(bits, cursor, headerCursor, { true, false });
|
||||
// write_sector_header(bits, cursor, logicalTrack, 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 });
|
||||
double clockRateUs = 1e3 / clockRateKhz / 2.0;
|
||||
int bitsPerRevolution = (trackLengthMs * 1000.0) / clockRateUs;
|
||||
_bits.resize(bitsPerRevolution);
|
||||
_cursor = 0;
|
||||
|
||||
// The pre-index gap is not normally reported.
|
||||
// std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl;
|
||||
uint8_t am1Unencoded = decodeUint16(am1Byte);
|
||||
uint8_t am2Unencoded = decodeUint16(am2Byte);
|
||||
|
||||
writeBytes(gap1, 0x55);
|
||||
|
||||
bool first = true;
|
||||
for (char sectorChar : sectorSkew.get())
|
||||
{
|
||||
int sectorId = charToInt(sectorChar);
|
||||
if (!first)
|
||||
writeBytes(gap3, 0x55);
|
||||
first = false;
|
||||
|
||||
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
|
||||
if (!sectorData)
|
||||
Error() << fmt::format("format tried to find sector {} which wasn't in the input file", sectorId);
|
||||
|
||||
/* Writing the sector and data records are fantastically annoying.
|
||||
* The CRC is calculated from the *very start* of the record, and
|
||||
* include the malformed marker bytes. Our encoder doesn't know
|
||||
* about this, of course, with the result that we have to construct
|
||||
* the unencoded header, calculate the checksum, and then use the
|
||||
* same logic to emit the bytes which require special encoding
|
||||
* before encoding the rest of the header normally. */
|
||||
|
||||
{
|
||||
Bytes header;
|
||||
ByteWriter bw(header);
|
||||
|
||||
writeBytes(12, 0x55);
|
||||
bw.write_8(am1Unencoded);
|
||||
bw.write_8(sectorData->logicalSide << 3);
|
||||
bw.write_8(sectorData->logicalTrack);
|
||||
bw.write_8(sectorCount);
|
||||
bw.write_8(sectorData->logicalSector);
|
||||
bw.write_be16(sectorData->data.size());
|
||||
uint16_t crc = crc16(CCITT_POLY, header);
|
||||
bw.write_be16(crc);
|
||||
|
||||
writeRawBits(am1Byte, 16);
|
||||
writeBytes(header.slice(1));
|
||||
}
|
||||
|
||||
writeBytes(gap2, 0x55);
|
||||
|
||||
{
|
||||
Bytes data;
|
||||
ByteWriter bw(data);
|
||||
|
||||
writeBytes(12, 0x55);
|
||||
bw.write_8(am2Unencoded);
|
||||
|
||||
bw += sectorData->data;
|
||||
uint16_t crc = crc16(CCITT_POLY, data);
|
||||
bw.write_be16(crc);
|
||||
|
||||
writeRawBits(am2Byte, 16);
|
||||
writeBytes(data.slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (_cursor >= _bits.size())
|
||||
Error() << "track data overrun";
|
||||
while (_cursor < _bits.size())
|
||||
writeBytes(1, 0x55);
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
// fluxmap->appendBits(bits, clockRateUs*1e3);
|
||||
fluxmap->appendBits(_bits, clockRateUs*1e3);
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,19 @@ class TiDs990Encoder : public AbstractEncoder
|
||||
public:
|
||||
virtual ~TiDs990Encoder() {}
|
||||
|
||||
private:
|
||||
void writeRawBits(uint32_t data, int width);
|
||||
void writeBytes(const Bytes& bytes);
|
||||
void writeBytes(int count, uint8_t value);
|
||||
void writeSync();
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
|
||||
private:
|
||||
std::vector<bool> _bits;
|
||||
unsigned _cursor;
|
||||
bool _lastBit;
|
||||
};
|
||||
|
||||
extern FlagGroup tids990EncoderFlags;
|
||||
|
||||
@@ -12,7 +12,7 @@ static FlagGroup flags { &writerFlags, &tids990EncoderFlags };
|
||||
int mainWriteTiDs990(int argc, const char* argv[])
|
||||
{
|
||||
setWriterDefaultInput(":c=77:h=2:s=26:b=288");
|
||||
setWriterDefaultDest(":d=0:t=0-77");
|
||||
setWriterDefaultDest(":d=0:t=0-76:s=0-1");
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
TiDs990Encoder encoder;
|
||||
|
||||
Reference in New Issue
Block a user