Refactor to use FluxmapReader.

This commit is contained in:
David Given
2019-03-09 11:30:50 +01:00
parent 574d383573
commit 456791e20c
9 changed files with 174 additions and 62 deletions

View File

@@ -4,6 +4,7 @@
#include "decoders.h"
#include "record.h"
#include "protocol.h"
#include "rawbits.h"
#include "fmt/format.h"
static DoubleFlag clockDecodeThreshold(
@@ -44,9 +45,13 @@ nanoseconds_t Fluxmap::guessClock() const
uint32_t buckets[256] = {};
size_t cursor = 0;
FluxmapReader fr(*this);
while (cursor < bytes())
{
uint32_t interval = getAndIncrement(cursor);
unsigned interval;
int opcode = fr.readPulse(interval);
if (opcode != 0x80)
break;
if (interval > 0xff)
continue;
buckets[interval]++;
@@ -152,35 +157,39 @@ nanoseconds_t Fluxmap::guessClock() const
}
/* Decodes a fluxmap into a nice aligned array of bits. */
std::vector<bool> Fluxmap::decodeToBits(nanoseconds_t clockPeriod) const
const RawBits Fluxmap::decodeToBits(nanoseconds_t clockPeriod) const
{
int pulses = duration() / clockPeriod;
nanoseconds_t lowerThreshold = clockPeriod * clockDecodeThreshold;
std::vector<bool> bitmap(pulses);
auto bitmap = std::make_unique<std::vector<bool>>(pulses);
auto indices = std::make_unique<std::vector<size_t>>();
unsigned count = 0;
size_t cursor = 0;
nanoseconds_t timestamp = 0;
FluxmapReader fr(*this);
for (;;)
{
while (timestamp < lowerThreshold)
{
if (cursor >= bytes())
unsigned interval;
int opcode = fr.readPulse(interval);
if (opcode == -1)
goto abort;
uint8_t interval = getAndIncrement(cursor);
timestamp += interval * NS_PER_TICK;
}
int clocks = (timestamp + clockPeriod/2) / clockPeriod;
count += clocks;
if (count >= bitmap.size())
if (count >= bitmap->size())
goto abort;
bitmap[count] = true;
bitmap->at(count) = true;
timestamp = 0;
}
abort:
return bitmap;
RawBits rawbits(std::move(bitmap), std::move(indices));
return rawbits;
}
nanoseconds_t AbstractDecoder::guessClock(Fluxmap& fluxmap) const
@@ -188,7 +197,7 @@ nanoseconds_t AbstractDecoder::guessClock(Fluxmap& fluxmap) const
return fluxmap.guessClock();
}
RawRecordVector AbstractSoftSectorDecoder::extractRecords(std::vector<bool> bits) const
RawRecordVector AbstractSoftSectorDecoder::extractRecords(const RawBits& rawbits) const
{
RawRecordVector records;
uint64_t fifo = 0;
@@ -204,15 +213,15 @@ RawRecordVector AbstractSoftSectorDecoder::extractRecords(std::vector<bool> bits
std::unique_ptr<RawRecord>(
new RawRecord(
matchStart,
bits.begin() + matchStart,
bits.begin() + end)
rawbits.begin() + matchStart,
rawbits.begin() + end)
)
);
};
while (cursor < bits.size())
while (cursor < rawbits.size())
{
fifo = (fifo << 1) | bits[cursor++];
fifo = (fifo << 1) | rawbits[cursor++];
int match = recordMatcher(fifo);
if (match > 0)
@@ -226,3 +235,29 @@ RawRecordVector AbstractSoftSectorDecoder::extractRecords(std::vector<bool> bits
return records;
}
RawRecordVector AbstractHardSectorDecoder::extractRecords(const RawBits& rawbits) const
{
RawRecordVector records;
int matchStart = 0;
auto pushRecord = [&](size_t end)
{
records.push_back(
std::unique_ptr<RawRecord>(
new RawRecord(
matchStart,
rawbits.begin() + matchStart,
rawbits.begin() + end)
)
);
matchStart = end;
};
for (size_t index : rawbits.indices())
pushRecord(index);
pushRecord(rawbits.size());
return records;
}

View File

@@ -6,6 +6,8 @@
class Sector;
class Fluxmap;
class RawRecord;
class RawBits;
typedef std::vector<std::unique_ptr<RawRecord>> RawRecordVector;
typedef std::vector<std::unique_ptr<Sector>> SectorVector;
@@ -17,7 +19,7 @@ public:
virtual ~AbstractDecoder() {}
virtual nanoseconds_t guessClock(Fluxmap& fluxmap) const;
virtual RawRecordVector extractRecords(std::vector<bool> bits) const = 0;
virtual RawRecordVector extractRecords(const RawBits& rawbits) const = 0;
virtual SectorVector decodeToSectors(const RawRecordVector& rawrecords,
unsigned physicalTrack) = 0;
};
@@ -27,9 +29,17 @@ class AbstractSoftSectorDecoder : public AbstractDecoder
public:
virtual ~AbstractSoftSectorDecoder() {}
RawRecordVector extractRecords(std::vector<bool> bits) const;
RawRecordVector extractRecords(const RawBits& rawbits) const;
virtual int recordMatcher(uint64_t fifo) const = 0;
};
class AbstractHardSectorDecoder : public AbstractDecoder
{
public:
virtual ~AbstractHardSectorDecoder() {}
RawRecordVector extractRecords(const RawBits& bits) const;
};
#endif

35
lib/decoders/rawbits.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef RAWBITS_H
#define RAWBITS_H
class RawBits
{
public:
RawBits(std::unique_ptr<std::vector<bool>> bits,
std::unique_ptr<std::vector<size_t>> indices):
_bits(std::move(bits)),
_indices(std::move(indices))
{}
typedef std::vector<bool>::const_iterator const_iterator;
const_iterator begin() const
{ return _bits->begin(); }
const_iterator end() const
{ return _bits->end(); }
size_t size() const
{ return _bits->size(); }
const bool operator[] (size_t pos) const
{ return _bits->at(pos); }
const std::vector<size_t> indices() const
{ return *_indices; }
private:
std::unique_ptr<std::vector<bool>> _bits;
std::unique_ptr<std::vector<size_t>> _indices;
};
#endif

View File

@@ -2,23 +2,6 @@
#include "fluxmap.h"
#include "protocol.h"
uint32_t Fluxmap::getAndIncrement(size_t& index) const
{
uint32_t ticks = 0;
while (index < _bytes.size())
{
uint8_t b = _bytes[index++];
if (b < 0x80)
ticks += b;
if (b == 0x80)
break;
/* everything above 0x80 is ignored for now */
}
return ticks;
}
Fluxmap& Fluxmap::appendBytes(const Bytes& bytes)
{
return appendBytes(&bytes[0], bytes.size());
@@ -89,3 +72,33 @@ void Fluxmap::precompensate(int threshold_ticks, int amount_ticks)
}
}
}
int FluxmapReader::read(unsigned& ticks)
{
ticks = 0;
while (_cursor < _size)
{
uint8_t b = _bytes[_cursor++];
if (b < 0x80)
ticks += b;
else
return b;
}
return -1;
}
int FluxmapReader::readPulse(unsigned& ticks)
{
ticks = 0;
for (;;)
{
unsigned thisTicks;
int opcode = read(thisTicks);
ticks += thisTicks;
if ((opcode == -1) || (opcode == 0x80))
return opcode;
}
}

View File

@@ -3,11 +3,11 @@
#include "bytes.h"
class RawBits;
class Fluxmap
{
public:
uint32_t getAndIncrement(size_t& index) const;
nanoseconds_t duration() const { return _duration; }
size_t bytes() const { return _bytes.size(); }
const Bytes& rawBytes() const { return _bytes; }
@@ -31,7 +31,7 @@ public:
}
nanoseconds_t guessClock() const;
std::vector<bool> decodeToBits(nanoseconds_t clock_period) const;
const RawBits decodeToBits(nanoseconds_t clock_period) const;
Fluxmap& appendBits(const std::vector<bool>& bits, nanoseconds_t clock);
@@ -43,4 +43,30 @@ private:
Bytes _bytes;
};
class FluxmapReader
{
public:
FluxmapReader(const Fluxmap& fluxmap):
_fluxmap(fluxmap),
_bytes(fluxmap.ptr()),
_size(fluxmap.bytes())
{
rewind();
}
FluxmapReader(const Fluxmap&& fluxmap) = delete;
void rewind()
{ _cursor = 0; }
int read(unsigned& ticks);
int readPulse(unsigned& ticks);
private:
const Fluxmap& _fluxmap;
const uint8_t* _bytes;
const size_t _size;
size_t _cursor;
};
#endif

View File

@@ -12,6 +12,7 @@
#include "record.h"
#include "image.h"
#include "bytes.h"
#include "rawbits.h"
#include "fmt/format.h"
static DataSpecFlag source(
@@ -154,7 +155,7 @@ void readDiskCommand(AbstractDecoder& decoder, const std::string& outputFilename
}
std::cout << fmt::format(" {:.2f} us clock; ", (double)clockPeriod/1000.0) << std::flush;
auto bitmap = fluxmap->decodeToBits(clockPeriod);
const auto& bitmap = fluxmap->decodeToBits(clockPeriod);
std::cout << fmt::format("{} bytes encoded; ", bitmap.size()/8) << std::flush;
auto rawrecords = decoder.extractRecords(bitmap);

View File

@@ -27,22 +27,7 @@ SectorVector ZilogMczDecoder::decodeToSectors(
auto reversed = reverseBits(sliceddata);
const auto rawbytes = decodeFmMfm(reversed);
hexdump(std::cout, rawbytes);
std::cout << std::endl;
}
return sectors;
}
int ZilogMczDecoder::recordMatcher(uint64_t fifo) const
{
uint32_t masked = fifo & 0xffffffff;
if (masked == ZILOGMCZ_RECORD_SEPARATOR)
return 31;
return 0;
}
RawRecordVector ZilogMczDecoder::extractRecords(std::vector<bool> bits) const
{
return AbstractSoftSectorDecoder::extractRecords(reverseBits(bits));
}

View File

@@ -1,19 +1,15 @@
#ifndef ZILOGMCZ_H
#define ZILOGMCZ_H
#define ZILOGMCZ_RECORD_SEPARATOR 0xffff5d75
class Sector;
class Fluxmap;
class ZilogMczDecoder : public AbstractSoftSectorDecoder
class ZilogMczDecoder : public AbstractHardSectorDecoder
{
public:
virtual ~ZilogMczDecoder() {}
SectorVector decodeToSectors(const RawRecordVector& rawRecords, unsigned physicalTrack);
int recordMatcher(uint64_t fifo) const;
RawRecordVector extractRecords(std::vector<bool> bits) const;
};
#endif

View File

@@ -5,6 +5,7 @@
#include "decoders.h"
#include "image.h"
#include "protocol.h"
#include "rawbits.h"
#include <fmt/format.h>
static DoubleFlag clockScaleFlag(
@@ -51,7 +52,7 @@ int main(int argc, const char* argv[])
clockPeriod *= clockScaleFlag;
std::cout << fmt::format("{:.2f} us bit clock; ", (double)clockPeriod/1000.0) << std::flush;
auto bitmap = fluxmap->decodeToBits(clockPeriod);
const auto& bitmap = fluxmap->decodeToBits(clockPeriod);
std::cout << fmt::format("{} bytes encoded.", bitmap.size()/8) << std::endl;
if (dumpFluxFlag)
@@ -69,9 +70,14 @@ int main(int argc, const char* argv[])
size_t cursor = 0;
nanoseconds_t seekto = seekFlag*1000000.0;
int ticks = 0;
while (cursor < fluxmap->bytes())
FluxmapReader fr(*fluxmap);
for (;;)
{
ticks += fluxmap->getAndIncrement(cursor);
unsigned interval;
int opcode = fr.readPulse(interval);
if (opcode == -1)
break;
ticks += interval;
now = ticks * NS_PER_TICK;
if (now >= seekto)
@@ -80,9 +86,14 @@ int main(int argc, const char* argv[])
std::cout << fmt::format("{: 10.3f}:-", ticks*US_PER_TICK);
nanoseconds_t lasttransition = 0;
while (cursor < fluxmap->bytes())
fr.rewind();
for (;;)
{
ticks += fluxmap->getAndIncrement(cursor);
unsigned interval;
int opcode = fr.readPulse(interval);
if (opcode == -1)
break;
ticks += interval;
nanoseconds_t transition = ticks*NS_PER_TICK;
nanoseconds_t next;