diff --git a/arch/aeslanier/decoder.cc b/arch/aeslanier/decoder.cc index de22cd8c..16aceb79 100644 --- a/arch/aeslanier/decoder.cc +++ b/arch/aeslanier/decoder.cc @@ -4,6 +4,7 @@ #include "lib/core/crc.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/sector.h" #include "lib/core/bytes.h" #include "fmt/format.h" diff --git a/arch/agat/decoder.cc b/arch/agat/decoder.cc index 2f99dba9..4cd81c75 100644 --- a/arch/agat/decoder.cc +++ b/arch/agat/decoder.cc @@ -4,6 +4,7 @@ #include "lib/core/crc.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/sector.h" #include "lib/core/bytes.h" #include "fmt/format.h" diff --git a/arch/amiga/decoder.cc b/arch/amiga/decoder.cc index f745a331..8ff1c7d6 100644 --- a/arch/amiga/decoder.cc +++ b/arch/amiga/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "protocol.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" diff --git a/arch/apple2/decoder.cc b/arch/apple2/decoder.cc index 840c9b22..98804dd4 100644 --- a/arch/apple2/decoder.cc +++ b/arch/apple2/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "protocol.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" diff --git a/arch/brother/decoder.cc b/arch/brother/decoder.cc index af6096ab..3e41bf59 100644 --- a/arch/brother/decoder.cc +++ b/arch/brother/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/decoders/decoders.h" #include "lib/encoders/encoders.h" #include "brother.h" diff --git a/arch/c64/decoder.cc b/arch/c64/decoder.cc index 66fe5a2c..ac34f29c 100644 --- a/arch/c64/decoder.cc +++ b/arch/c64/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "protocol.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" diff --git a/arch/f85/decoder.cc b/arch/f85/decoder.cc index f67b007f..1232cb5e 100644 --- a/arch/f85/decoder.cc +++ b/arch/f85/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "protocol.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" diff --git a/arch/fb100/decoder.cc b/arch/fb100/decoder.cc index ff2bec98..83e5c1b9 100644 --- a/arch/fb100/decoder.cc +++ b/arch/fb100/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "protocol.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" diff --git a/arch/ibm/decoder.cc b/arch/ibm/decoder.cc index 22ca1af9..cb24f897 100644 --- a/arch/ibm/decoder.cc +++ b/arch/ibm/decoder.cc @@ -4,6 +4,7 @@ #include "lib/core/crc.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/sector.h" #include "arch/ibm/ibm.pb.h" #include "lib/proto.h" diff --git a/arch/macintosh/decoder.cc b/arch/macintosh/decoder.cc index d5514284..9e6bee61 100644 --- a/arch/macintosh/decoder.cc +++ b/arch/macintosh/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "protocol.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" diff --git a/arch/micropolis/decoder.cc b/arch/micropolis/decoder.cc index dc819c0e..63ae43cb 100644 --- a/arch/micropolis/decoder.cc +++ b/arch/micropolis/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" #include "micropolis.h" diff --git a/arch/mx/decoder.cc b/arch/mx/decoder.cc index eeb6b90d..a7758a18 100644 --- a/arch/mx/decoder.cc +++ b/arch/mx/decoder.cc @@ -4,6 +4,7 @@ #include "lib/core/crc.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/sector.h" #include diff --git a/arch/northstar/decoder.cc b/arch/northstar/decoder.cc index 1d48a82d..4c5420d8 100644 --- a/arch/northstar/decoder.cc +++ b/arch/northstar/decoder.cc @@ -14,6 +14,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" #include "northstar.h" diff --git a/arch/rolandd20/decoder.cc b/arch/rolandd20/decoder.cc index 11675ff9..629d9b24 100644 --- a/arch/rolandd20/decoder.cc +++ b/arch/rolandd20/decoder.cc @@ -3,6 +3,7 @@ #include "lib/core/crc.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/sector.h" #include "lib/core/bytes.h" #include "rolandd20.h" diff --git a/arch/smaky6/decoder.cc b/arch/smaky6/decoder.cc index 21ce96de..d2496c39 100644 --- a/arch/smaky6/decoder.cc +++ b/arch/smaky6/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "protocol.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" diff --git a/arch/tartu/decoder.cc b/arch/tartu/decoder.cc index 16aa946e..8da1507e 100644 --- a/arch/tartu/decoder.cc +++ b/arch/tartu/decoder.cc @@ -5,16 +5,20 @@ #include "lib/core/crc.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/sector.h" #include constexpr uint64_t HEADER_BITS = 0xaaaaaaaa44895554LL; -constexpr uint64_t DATA_BITS = 0xaaaaaaaa44895545LL; +constexpr uint64_t DATA_BITS = 0xaaaaaaaa44895545LL; static const FluxPattern HEADER_PATTERN(64, HEADER_BITS); static const FluxPattern DATA_PATTERN(64, DATA_BITS); -const FluxMatchers ANY_RECORD_PATTERN{&HEADER_PATTERN, &DATA_PATTERN}; +const FluxMatchers ANY_RECORD_PATTERN { + &HEADER_PATTERN, + &DATA_PATTERN +}; class TartuDecoder : public Decoder { @@ -25,7 +29,9 @@ public: { } - void beginTrack() override {} + void beginTrack() override + { + } nanoseconds_t advanceToNextRecord() override { @@ -39,7 +45,7 @@ public: auto bits = readRawBits(16 * 4); auto bytes = decodeFmMfm(bits).slice(0, 4); - + ByteReader br(bytes); uint8_t track = br.read_8(); _sector->logicalTrack = track >> 1; @@ -48,7 +54,7 @@ public: _sector->logicalSector = br.read_8(); uint8_t wantChecksum = br.read_8(); uint8_t gotChecksum = ~sumBytes(bytes.slice(0, 3)); - + if (wantChecksum == gotChecksum) _sector->status = Sector::DATA_MISSING; @@ -59,15 +65,14 @@ public: { if (readRaw64() != DATA_BITS) return; - + const auto& bits = readRawBits(129 * 16); const auto& bytes = decodeFmMfm(bits).slice(0, 129); _sector->data = bytes.slice(0, 128); uint8_t wantChecksum = bytes.reader().seek(128).read_8(); uint8_t gotChecksum = ~sumBytes(_sector->data); - _sector->status = - (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM; + _sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM; } private: @@ -78,3 +83,4 @@ std::unique_ptr createTartuDecoder(const DecoderProto& config) { return std::unique_ptr(new TartuDecoder(config)); } + diff --git a/arch/tids990/decoder.cc b/arch/tids990/decoder.cc index bf3718a2..00951405 100644 --- a/arch/tids990/decoder.cc +++ b/arch/tids990/decoder.cc @@ -5,6 +5,7 @@ #include "lib/core/crc.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "lib/sector.h" #include #include diff --git a/arch/victor9k/decoder.cc b/arch/victor9k/decoder.cc index 6468548a..e8fecf64 100644 --- a/arch/victor9k/decoder.cc +++ b/arch/victor9k/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "protocol.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" diff --git a/arch/zilogmcz/decoder.cc b/arch/zilogmcz/decoder.cc index 0ea39a7e..1e315cd4 100644 --- a/arch/zilogmcz/decoder.cc +++ b/arch/zilogmcz/decoder.cc @@ -1,6 +1,7 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include "protocol.h" #include "lib/decoders/decoders.h" #include "lib/sector.h" diff --git a/build.py b/build.py index 1d894c96..46b78493 100644 --- a/build.py +++ b/build.py @@ -29,6 +29,7 @@ cxxlibrary( "./lib/decoders/decoders.cc", "./lib/decoders/fluxdecoder.cc", "./lib/decoders/fluxmapreader.cc", + "./lib/decoders/fluxpattern.cc", "./lib/decoders/fmmfm.cc", "./lib/encoders/encoders.cc", "./lib/fl2.cc", @@ -159,6 +160,7 @@ cxxlibrary( "lib/decoders/decoders.h": "./lib/decoders/decoders.h", "lib/decoders/fluxdecoder.h": "./lib/decoders/fluxdecoder.h", "lib/decoders/fluxmapreader.h": "./lib/decoders/fluxmapreader.h", + "lib/decoders/fluxpattern.h": "./lib/decoders/fluxpattern.h", "lib/decoders/rawbits.h": "./lib/decoders/rawbits.h", "lib/encoders/encoders.h": "./lib/encoders/encoders.h", "lib/scp.h": "./lib/scp.h", diff --git a/lib/core/utils.cc b/lib/core/utils.cc index 23452e9c..8ccefb8d 100644 --- a/lib/core/utils.cc +++ b/lib/core/utils.cc @@ -220,3 +220,17 @@ uint32_t unbcd(uint32_t bcd) return dec; } + +int findLowestSetBit(uint64_t value) +{ + if (!value) + return 0; + int bit = 1; + while (!(value & 1)) + { + value >>= 1; + bit++; + } + return bit; +} + diff --git a/lib/core/utils.h b/lib/core/utils.h index 489da6a9..89e87a9a 100644 --- a/lib/core/utils.h +++ b/lib/core/utils.h @@ -21,6 +21,7 @@ extern std::string tohex(const std::string& s); extern bool doesFileExist(const std::string& filename); extern int countSetBits(uint32_t word); extern uint32_t unbcd(uint32_t bcd); +extern int findLowestSetBit(uint64_t value); template std::map reverseMap(const std::map& map) diff --git a/lib/decoders/decoders.h b/lib/decoders/decoders.h index 775e3550..819fc05b 100644 --- a/lib/decoders/decoders.h +++ b/lib/decoders/decoders.h @@ -8,6 +8,7 @@ class Sector; class Fluxmap; +class FluxMatcher; class FluxmapReader; class RawBits; class DecoderProto; diff --git a/lib/decoders/fluxmapreader.cc b/lib/decoders/fluxmapreader.cc index 459ec5ba..1ec1be79 100644 --- a/lib/decoders/fluxmapreader.cc +++ b/lib/decoders/fluxmapreader.cc @@ -2,7 +2,7 @@ #include "lib/config.h" #include "lib/fluxmap.h" #include "lib/decoders/fluxmapreader.h" -#include "lib/flags.h" +#include "lib/decoders/fluxpattern.h" #include "lib/proto.h" #include "protocol.h" #include @@ -81,110 +81,6 @@ unsigned FluxmapReader::readInterval(nanoseconds_t clock) return ticks; } -static int findLowestSetBit(uint64_t value) -{ - if (!value) - return 0; - int bit = 1; - while (!(value & 1)) - { - value >>= 1; - bit++; - } - return bit; -} - -FluxPattern::FluxPattern(unsigned bits, uint64_t pattern): _bits(bits) -{ - const uint64_t TOPBIT = 1ULL << 63; - - assert(pattern != 0); - - unsigned lowbit = findLowestSetBit(pattern) - 1; - - pattern <<= 64 - bits; - _highzeroes = 0; - while (!(pattern & TOPBIT)) - { - pattern <<= 1; - _highzeroes++; - } - - _length = 0; - while (pattern != TOPBIT) - { - unsigned interval = 0; - do - { - pattern <<= 1; - interval++; - } while (!(pattern & TOPBIT)); - _intervals.push_back(interval); - _length += interval; - } - - if (lowbit) - { - _lowzero = true; - /* Note that length does *not* include this interval. */ - _intervals.push_back(lowbit + 1); - } -} - -bool FluxPattern::matches(const unsigned* end, FluxMatch& match) const -{ - const double clockDecodeThreshold = - globalConfig()->decoder().bit_error_threshold(); - const unsigned* start = end - _intervals.size(); - unsigned candidatelength = std::accumulate(start, end - _lowzero, 0); - if (!candidatelength) - return false; - match.clock = (double)candidatelength / (double)_length; - - unsigned exactIntervals = _intervals.size() - _lowzero; - for (unsigned i = 0; i < exactIntervals; i++) - { - double ii = match.clock * (double)_intervals[i]; - double ci = (double)start[i]; - double error = fabs((ii - ci) / match.clock); - if (error > clockDecodeThreshold) - return false; - } - - if (_lowzero) - { - double ii = match.clock * (double)_intervals[exactIntervals]; - double ci = (double)start[exactIntervals]; - double error = (ii - ci) / match.clock; - if (error > clockDecodeThreshold) - return false; - } - - match.matcher = this; - match.intervals = _intervals.size(); - match.zeroes = _highzeroes; - return true; -} - -FluxMatchers::FluxMatchers( - const std::initializer_list matchers): - _matchers(matchers) -{ - _intervals = 0; - for (const auto* matcher : matchers) - _intervals = std::max(_intervals, matcher->intervals()); -} - -bool FluxMatchers::matches(const unsigned* intervals, FluxMatch& match) const -{ - for (const auto* matcher : _matchers) - { - if (matcher->matches(intervals, match)) - return true; - } - return false; -} - void FluxmapReader::seek(nanoseconds_t ns) { unsigned ticks = ns / NS_PER_TICK; diff --git a/lib/decoders/fluxmapreader.h b/lib/decoders/fluxmapreader.h index e154b8f0..1f14bd68 100644 --- a/lib/decoders/fluxmapreader.h +++ b/lib/decoders/fluxmapreader.h @@ -5,67 +5,8 @@ #include "lib/flags.h" #include "protocol.h" -class FluxMatcher; class DecoderProto; - -struct FluxMatch -{ - const FluxMatcher* matcher; - unsigned intervals; - double clock; - unsigned zeroes; -}; - -class FluxMatcher -{ -public: - virtual ~FluxMatcher() {} - - /* Returns the number of intervals matched */ - virtual bool matches(const unsigned* intervals, FluxMatch& match) const = 0; - virtual unsigned intervals() const = 0; -}; - -class FluxPattern : public FluxMatcher -{ -public: - FluxPattern(unsigned bits, uint64_t patterns); - - bool matches(const unsigned* intervals, FluxMatch& match) const override; - - unsigned intervals() const override - { - return _intervals.size(); - } - -private: - std::vector _intervals; - unsigned _length; - unsigned _bits; - unsigned _highzeroes; - bool _lowzero = false; - -public: - friend void test_patternconstruction(); - friend void test_patternmatching(); -}; - -class FluxMatchers : public FluxMatcher -{ -public: - FluxMatchers(const std::initializer_list matchers); - - bool matches(const unsigned* intervals, FluxMatch& match) const override; - - unsigned intervals() const override - { - return _intervals; - } - -private: - unsigned _intervals; - std::vector _matchers; -}; +class FluxMatcher; class FluxmapReader { diff --git a/lib/decoders/fluxpattern.cc b/lib/decoders/fluxpattern.cc new file mode 100644 index 00000000..4836b54c --- /dev/null +++ b/lib/decoders/fluxpattern.cc @@ -0,0 +1,100 @@ +#include "lib/core/globals.h" +#include "lib/config.h" +#include "lib/fluxmap.h" +#include "lib/decoders/fluxpattern.h" +#include "lib/proto.h" +#include "protocol.h" +#include +#include +#include + +FluxPattern::FluxPattern(unsigned bits, uint64_t pattern): _bits(bits) +{ + const uint64_t TOPBIT = 1ULL << 63; + + assert(pattern != 0); + + unsigned lowbit = findLowestSetBit(pattern) - 1; + + pattern <<= 64 - bits; + _highzeroes = 0; + while (!(pattern & TOPBIT)) + { + pattern <<= 1; + _highzeroes++; + } + + _length = 0; + while (pattern != TOPBIT) + { + unsigned interval = 0; + do + { + pattern <<= 1; + interval++; + } while (!(pattern & TOPBIT)); + _intervals.push_back(interval); + _length += interval; + } + + if (lowbit) + { + _lowzero = true; + /* Note that length does *not* include this interval. */ + _intervals.push_back(lowbit + 1); + } +} + +bool FluxPattern::matches(const unsigned* end, FluxMatch& match) const +{ + const double clockDecodeThreshold = + globalConfig()->decoder().bit_error_threshold(); + const unsigned* start = end - _intervals.size(); + unsigned candidatelength = std::accumulate(start, end - _lowzero, 0); + if (!candidatelength) + return false; + match.clock = (double)candidatelength / (double)_length; + + unsigned exactIntervals = _intervals.size() - _lowzero; + for (unsigned i = 0; i < exactIntervals; i++) + { + double ii = match.clock * (double)_intervals[i]; + double ci = (double)start[i]; + double error = fabs((ii - ci) / match.clock); + if (error > clockDecodeThreshold) + return false; + } + + if (_lowzero) + { + double ii = match.clock * (double)_intervals[exactIntervals]; + double ci = (double)start[exactIntervals]; + double error = (ii - ci) / match.clock; + if (error > clockDecodeThreshold) + return false; + } + + match.matcher = this; + match.intervals = _intervals.size(); + match.zeroes = _highzeroes; + return true; +} + +FluxMatchers::FluxMatchers( + const std::initializer_list matchers): + _matchers(matchers) +{ + _intervals = 0; + for (const auto* matcher : matchers) + _intervals = std::max(_intervals, matcher->intervals()); +} + +bool FluxMatchers::matches(const unsigned* intervals, FluxMatch& match) const +{ + for (const auto* matcher : _matchers) + { + if (matcher->matches(intervals, match)) + return true; + } + return false; +} diff --git a/lib/decoders/fluxpattern.h b/lib/decoders/fluxpattern.h new file mode 100644 index 00000000..262dfd99 --- /dev/null +++ b/lib/decoders/fluxpattern.h @@ -0,0 +1,68 @@ +#pragma once + +#include "lib/core/utils.h" +#include "lib/fluxmap.h" +#include "lib/flags.h" +#include "protocol.h" + +class FluxMatcher; +class DecoderProto; + +struct FluxMatch +{ + const FluxMatcher* matcher; + unsigned intervals; + double clock; + unsigned zeroes; +}; + +class FluxMatcher +{ +public: + virtual ~FluxMatcher() {} + + /* Returns the number of intervals matched */ + virtual bool matches(const unsigned* intervals, FluxMatch& match) const = 0; + virtual unsigned intervals() const = 0; +}; + +class FluxPattern : public FluxMatcher +{ +public: + FluxPattern(unsigned bits, uint64_t patterns); + + bool matches(const unsigned* intervals, FluxMatch& match) const override; + + unsigned intervals() const override + { + return _intervals.size(); + } + +private: + std::vector _intervals; + unsigned _length; + unsigned _bits; + unsigned _highzeroes; + bool _lowzero = false; + +public: + friend void test_patternconstruction(); + friend void test_patternmatching(); +}; + +class FluxMatchers : public FluxMatcher +{ +public: + FluxMatchers(const std::initializer_list matchers); + + bool matches(const unsigned* intervals, FluxMatch& match) const override; + + unsigned intervals() const override + { + return _intervals; + } + +private: + unsigned _intervals; + std::vector _matchers; +}; diff --git a/tests/fluxpattern.cc b/tests/fluxpattern.cc index 571ad484..be82120e 100644 --- a/tests/fluxpattern.cc +++ b/tests/fluxpattern.cc @@ -1,6 +1,6 @@ #include "lib/core/globals.h" #include "lib/fluxmap.h" -#include "lib/decoders/fluxmapreader.h" +#include "lib/decoders/fluxpattern.h" #include typedef std::vector ivector;