From 5f8e0c846cf718e48cebd6f93ca7e3ac3c28bdb3 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 19 Apr 2019 00:55:01 +0200 Subject: [PATCH] Allow split decoders (into sector record and data record). --- lib/decoders/decoders.cc | 72 ++++++++++++++++++++ lib/decoders/decoders.h | 23 +++++++ lib/decoders/fluxmapreader.cc | 97 ++++++++++++++++++++------- lib/decoders/fluxmapreader.h | 75 +++++++++++++++------ lib/fb100/decoder.cc | 61 ++++++++--------- lib/fb100/fb100.h | 3 +- lib/fluxmap.h | 11 +++ lib/image.cc | 2 +- lib/macintosh/decoder.cc | 122 +++++++++++++++------------------- lib/macintosh/macintosh.h | 11 +-- lib/reader.cc | 4 +- lib/record.h | 16 ++--- lib/sector.cc | 1 + lib/sector.h | 4 +- lib/victor9k/victor9k.h | 2 +- src/fe-inspect.cc | 21 +++--- src/fe-readfb100.cc | 2 +- tests/fluxpattern.cc | 42 +++++++----- 18 files changed, 375 insertions(+), 194 deletions(-) diff --git a/lib/decoders/decoders.cc b/lib/decoders/decoders.cc index 090cc67d..c2d6c3a4 100644 --- a/lib/decoders/decoders.cc +++ b/lib/decoders/decoders.cc @@ -49,6 +49,9 @@ static const std::string BLOCK_ELEMENTS[] = */ nanoseconds_t Fluxmap::guessClock() const { + if (manualClockRate != 0.0) + return manualClockRate * 1000.0; + uint32_t buckets[256] = {}; FluxmapReader fr(*this); @@ -248,6 +251,7 @@ RawRecordVector AbstractSoftSectorDecoder::extractRecords(const RawBits& rawbits if (matchStart == -1) return; +#if 0 records.push_back( std::unique_ptr( new RawRecord( @@ -260,6 +264,7 @@ RawRecordVector AbstractSoftSectorDecoder::extractRecords(const RawBits& rawbits ) ) ); + #endif }; while (cursor < rawbits.size()) @@ -315,6 +320,7 @@ RawRecordVector AbstractHardSectorDecoder::extractRecords(const RawBits& rawbits if ((end - previous) < sectors_must_be_bigger_than) return; +#if 0 records.push_back( std::unique_ptr( new RawRecord( @@ -327,6 +333,7 @@ RawRecordVector AbstractHardSectorDecoder::extractRecords(const RawBits& rawbits ) ) ); + #endif previous = end; }; @@ -338,4 +345,69 @@ RawRecordVector AbstractHardSectorDecoder::extractRecords(const RawBits& rawbits return records; } +void AbstractStatefulDecoder::decodeToSectors(Track& track) +{ + Sector sector; + sector.physicalSide = track.physicalSide; + sector.physicalTrack = track.physicalTrack; + FluxmapReader fmr(*track.fluxmap); + for (;;) + { + nanoseconds_t clockPeriod = findSector(fmr, track); + if (fmr.eof() || !clockPeriod) + break; + + sector.status = Sector::MISSING; + sector.data.clear(); + sector.clock = clockPeriod; + _recordStart = sector.position = fmr.tell(); + + decodeSingleSector(fmr, track, sector); + pushRecord(fmr, track, sector); + if (sector.status != Sector::MISSING) + track.sectors.push_back(sector); + } +} + +void AbstractStatefulDecoder::pushRecord(FluxmapReader& fmr, Track& track, Sector& sector) +{ + RawRecord record; + record.physicalSide = track.physicalSide; + record.physicalTrack = track.physicalTrack; + record.clock = sector.clock; + record.position = _recordStart; + + Fluxmap::Position here = fmr.tell(); + fmr.seek(_recordStart); + record.data = toBytes(fmr.readRawBits(here, sector.clock)); + track.rawrecords.push_back(record); + _recordStart = here; +} + +void AbstractStatefulDecoder::discardRecord(FluxmapReader& fmr) +{ + _recordStart = fmr.tell(); +} + +void AbstractSplitDecoder::decodeSingleSector(FluxmapReader& fmr, Track& track, Sector& sector) +{ + decodeHeader(fmr, track, sector); + if (sector.status == Sector::MISSING) + return; + pushRecord(fmr, track, sector); + + nanoseconds_t clockPeriod = findData(fmr, track); + if (fmr.eof() || !clockPeriod) + return; + sector.clock = clockPeriod; + + discardRecord(fmr); + Fluxmap::Position pos = fmr.tell(); + decodeData(fmr, track, sector); + if (sector.status == Sector::DATA_MISSING) + { + fmr.seek(pos); + return; + } +} diff --git a/lib/decoders/decoders.h b/lib/decoders/decoders.h index 9e17d0f8..29885e0f 100644 --- a/lib/decoders/decoders.h +++ b/lib/decoders/decoders.h @@ -2,9 +2,12 @@ #define DECODERS_H #include "bytes.h" +#include "sector.h" +#include "record.h" class Sector; class Fluxmap; +class FluxmapReader; class RawRecord; class RawBits; class Track; @@ -67,6 +70,26 @@ public: class AbstractStatefulDecoder : public AbstractDecoder { +public: + void decodeToSectors(Track& track); + void discardRecord(FluxmapReader& fmr); + void pushRecord(FluxmapReader& fmr, Track& track, Sector& sector); + +protected: + virtual nanoseconds_t findSector(FluxmapReader& fmr, Track& track) = 0; + virtual void decodeSingleSector(FluxmapReader& fmr, Track& track, Sector& sector) = 0; + +private: + Fluxmap::Position _recordStart; +}; + +class AbstractSplitDecoder : public AbstractStatefulDecoder +{ + void decodeSingleSector(FluxmapReader& fmr, Track& track, Sector& sector) override; + + virtual nanoseconds_t findData(FluxmapReader& fmr, Track& track) = 0; + virtual void decodeHeader(FluxmapReader& fmr, Track& track, Sector& sector) = 0; + virtual void decodeData(FluxmapReader& fmr, Track& track, Sector& sector) = 0; }; #endif diff --git a/lib/decoders/fluxmapreader.cc b/lib/decoders/fluxmapreader.cc index 5767b1e8..1b82ca06 100644 --- a/lib/decoders/fluxmapreader.cc +++ b/lib/decoders/fluxmapreader.cc @@ -9,7 +9,7 @@ static DoubleFlag clockDecodeThreshold( { "--bit-error-threshold" }, "Amount of error to tolerate in pulse timing.", - 0.20); + 0.30); int FluxmapReader::readOpcode(unsigned& ticks) { @@ -47,17 +47,17 @@ unsigned FluxmapReader::readNextMatchingOpcode(uint8_t opcode) } } -FluxPattern::FluxPattern(unsigned len, uint64_t pattern) +FluxPattern::FluxPattern(unsigned bits, uint64_t pattern): + FluxMatcher(bits) { const uint64_t TOPBIT = 1ULL << 63; assert(pattern != 0); - bits = len; while (!(pattern & TOPBIT)) pattern <<= 1; - length = 0; + _length = 0; while (pattern != TOPBIT) { unsigned interval = 0; @@ -67,59 +67,98 @@ FluxPattern::FluxPattern(unsigned len, uint64_t pattern) interval++; } while (!(pattern & TOPBIT)); - intervals.push_back(interval); - length += interval; + _intervals.push_back(interval); + _length += interval; } } -bool FluxPattern::matches(const unsigned* end, double& clock) const +unsigned FluxPattern::matches(const unsigned* end, double& clock) const { - const unsigned* start = end - intervals.size(); + const unsigned* start = end - _intervals.size(); unsigned candidatelength = std::accumulate(start, end, 0); if (!candidatelength) - return false; - clock = (double)candidatelength / (double)length; + return 0; + clock = (double)candidatelength / (double)_length; - for (unsigned i=0; i clockDecodeThreshold) - return false; + return 0; } - return true; + return _intervals.size(); } -nanoseconds_t FluxmapReader::seekToPattern(const FluxPattern& pattern) +FluxPatterns::FluxPatterns(unsigned bits, std::initializer_list patterns): + FluxMatcher(bits) { - unsigned length = pattern.intervals.size(); - unsigned candidates[length]; - Position positions[length]; + _intervals = 0; + for (uint64_t p : patterns) + { + auto pattern = std::make_unique(bits, p); + _intervals = std::max(_intervals, pattern->intervals()); + _patterns.push_back(std::move(pattern)); + } +} + +unsigned FluxPatterns::matches(const unsigned* intervals, double& clock) const +{ + for (const auto& pattern : _patterns) + { + unsigned m = pattern->matches(intervals, clock); + if (m) + return m; + } + return 0; +} + +void FluxmapReader::seek(nanoseconds_t ns) +{ + unsigned ticks = ns / NS_PER_TICK; + if (ticks < _pos.ticks) + { + _pos.ticks = 0; + _pos.bytes = 0; + } + + while (!eof() && (_pos.ticks < ticks)) + { + unsigned t; + readOpcode(t); + } +} + +nanoseconds_t FluxmapReader::seekToPattern(const FluxMatcher& pattern) +{ + unsigned intervalCount = pattern.intervals(); + unsigned candidates[intervalCount+1]; + Fluxmap::Position positions[intervalCount+1]; for (unsigned& i : candidates) i = 0; - for (Position& p : positions) + for (Fluxmap::Position& p : positions) p = tell(); while (!eof()) { unsigned interval = readNextMatchingOpcode(F_OP_PULSE); - Position current = positions[0]; - for (unsigned i=0; i<(length-1); i++) + for (unsigned i=0; i FluxmapReader::readRawBits(unsigned count, nanoseconds_t clock result.push_back(readRawBit(clockPeriod)); return result; } + +std::vector FluxmapReader::readRawBits(const Fluxmap::Position& until, nanoseconds_t clockPeriod) +{ + std::vector result; + while (!eof() && (_pos.bytes < until.bytes)) + result.push_back(readRawBit(clockPeriod)); + return result; +} diff --git a/lib/decoders/fluxmapreader.h b/lib/decoders/fluxmapreader.h index 84c16e01..b9c99eed 100644 --- a/lib/decoders/fluxmapreader.h +++ b/lib/decoders/fluxmapreader.h @@ -4,27 +4,62 @@ #include "fluxmap.h" #include "protocol.h" -class FluxPattern +class FluxMatcher { public: - FluxPattern(unsigned len, uint64_t pattern); + FluxMatcher(unsigned bits): + _bits(bits) + {} - bool matches(const unsigned* intervals, double& clock) const; + virtual ~FluxMatcher() {} - unsigned bits; - std::vector intervals; - unsigned length; + /* Returns the number of intervals matched */ + virtual unsigned matches(const unsigned* intervals, double& clock) const = 0; + virtual unsigned intervals() const = 0; + + unsigned bits() const + { return _bits; } + +protected: + unsigned _bits; +}; + +class FluxPattern : public FluxMatcher +{ +public: + FluxPattern(unsigned bits, uint64_t patterns); + + unsigned matches(const unsigned* intervals, double& clock) const override; + + unsigned intervals() const override + { return _intervals.size(); } + +private: + std::vector _intervals; + unsigned _length; + +public: + friend void test_patternconstruction(); + friend void test_patternmatching(); +}; + +class FluxPatterns : public FluxMatcher +{ +public: + FluxPatterns(unsigned bits, std::initializer_list patterns); + + unsigned matches(const unsigned* intervals, double& clock) const override; + + unsigned intervals() const override + { return _intervals; } + +private: + unsigned _intervals; + std::vector> _patterns; }; class FluxmapReader { -public: - struct Position - { - unsigned bytes; - unsigned ticks; - }; - public: FluxmapReader(const Fluxmap& fluxmap): _fluxmap(fluxmap), @@ -46,30 +81,28 @@ public: bool eof() const { return _pos.bytes == _size; } - Position tell() const + Fluxmap::Position tell() const { return _pos; } - void seek(const Position& pos) - { _pos = pos; } - - nanoseconds_t tellNs() const - { return _pos.ticks * NS_PER_TICK; } + void seek(const Fluxmap::Position& pos) + { _pos = pos; _pendingZeroBits = 0; } int readOpcode(unsigned& ticks); unsigned readNextMatchingOpcode(uint8_t opcode); void seek(nanoseconds_t ns); void seekToIndexMark(); - nanoseconds_t seekToPattern(const FluxPattern& pattern); + nanoseconds_t seekToPattern(const FluxMatcher& pattern); bool readRawBit(nanoseconds_t clockPeriod); std::vector readRawBits(unsigned count, nanoseconds_t clockPeriod); + std::vector readRawBits(const Fluxmap::Position& until, nanoseconds_t clockPeriod); private: const Fluxmap& _fluxmap; const uint8_t* _bytes; const size_t _size; - Position _pos; + Fluxmap::Position _pos; unsigned _pendingZeroBits; }; diff --git a/lib/fb100/decoder.cc b/lib/fb100/decoder.cc index 447f509a..3e82f1b9 100644 --- a/lib/fb100/decoder.cc +++ b/lib/fb100/decoder.cc @@ -99,45 +99,36 @@ static uint16_t checksum(const Bytes& bytes) return (crchi << 8) | crclo; } -void Fb100Decoder::decodeToSectors(Track& track) +nanoseconds_t Fb100Decoder::findSector(FluxmapReader& fmr, Track& track) { - Sector sector; - sector.physicalSide = track.physicalSide; - sector.physicalTrack = track.physicalTrack; - RawRecord record; + return fmr.seekToPattern(SECTOR_ID_PATTERN); +} - FluxmapReader fmr(*track.fluxmap); +void Fb100Decoder::decodeSingleSector(FluxmapReader& fmr, Track& track, Sector& sector) +{ + auto rawbits = fmr.readRawBits(FB100_RECORD_SIZE*16, sector.clock); - for (;;) - { - nanoseconds_t clockPeriod = fmr.seekToPattern(SECTOR_ID_PATTERN); - if (fmr.eof() || !clockPeriod) - break; + const Bytes bytes = decodeFmMfm(rawbits).slice(0, FB100_RECORD_SIZE); + ByteReader br(bytes); + br.seek(1); + const Bytes id = br.read(FB100_ID_SIZE); + uint16_t wantIdCrc = br.read_be16(); + uint16_t gotIdCrc = checksum(id); + const Bytes payload = br.read(FB100_PAYLOAD_SIZE); + uint16_t wantPayloadCrc = br.read_be16(); + uint16_t gotPayloadCrc = checksum(payload); - sector.clock = record.clock = clockPeriod; - sector.position = record.position = fmr.tellNs(); - auto rawbits = fmr.readRawBits(FB100_RECORD_SIZE*16, clockPeriod); - record.bytes.writer().seekToEnd() += toBytes(rawbits); + if (wantIdCrc != gotIdCrc) + return; - const Bytes bytes = decodeFmMfm(rawbits).slice(0, FB100_RECORD_SIZE); - ByteReader br(bytes); - br.seek(1); - const Bytes id = br.read(FB100_ID_SIZE); - uint16_t wantIdCrc = br.read_be16(); - uint16_t gotIdCrc = checksum(id); - const Bytes payload = br.read(FB100_PAYLOAD_SIZE); - uint16_t wantPayloadCrc = br.read_be16(); - uint16_t gotPayloadCrc = checksum(payload); + uint8_t abssector = id[2]; + sector.logicalTrack = abssector >> 1; + sector.logicalSide = 0; + sector.logicalSector = abssector & 1; + sector.data.writer().append(id.slice(5, 12)).append(payload); - if (wantIdCrc != gotIdCrc) - continue; - - uint8_t abssector = id[2]; - sector.logicalTrack = abssector & 1; - sector.logicalSide = 0; - sector.logicalSector = abssector & 1; - sector.data.clear().writer().append(id.slice(5, 12)).append(payload); - sector.status = (wantPayloadCrc == gotPayloadCrc) ? Sector::OK : Sector::BAD_CHECKSUM; - track.sectors.push_back(sector); - } + if (wantPayloadCrc == gotPayloadCrc) + sector.status = Sector::OK; + else + sector.status = Sector::BAD_CHECKSUM; } \ No newline at end of file diff --git a/lib/fb100/fb100.h b/lib/fb100/fb100.h index 99283717..02971294 100644 --- a/lib/fb100/fb100.h +++ b/lib/fb100/fb100.h @@ -14,7 +14,8 @@ class Fb100Decoder : public AbstractStatefulDecoder public: virtual ~Fb100Decoder() {} - void decodeToSectors(Track& track) override; + nanoseconds_t findSector(FluxmapReader& fmr, Track& track) override; + void decodeSingleSector(FluxmapReader& fmr, Track& track, Sector& sector) override; }; #endif diff --git a/lib/fluxmap.h b/lib/fluxmap.h index 49a4d15a..8d64a992 100644 --- a/lib/fluxmap.h +++ b/lib/fluxmap.h @@ -2,11 +2,22 @@ #define FLUXMAP_H #include "bytes.h" +#include "protocol.h" class RawBits; class Fluxmap { +public: + struct Position + { + unsigned bytes = 0; + unsigned ticks = 0; + + nanoseconds_t ns() const + { return ticks * NS_PER_TICK; } + }; + public: nanoseconds_t duration() const { return _duration; } size_t bytes() const { return _bytes.size(); } diff --git a/lib/image.cc b/lib/image.cc index fe446f5f..e5973d6f 100644 --- a/lib/image.cc +++ b/lib/image.cc @@ -141,7 +141,7 @@ void writeSectorsToFile(const SectorSet& sectors, const Geometry& geometry, if (sector) { outputFile.seekp(sector->logicalTrack*trackSize + sector->logicalSide*headSize + sector->logicalSector*geometry.sectorSize, std::ios::beg); - outputFile.write((const char*) §or->data[0], sector->data.size()); + outputFile.write((const char*) sector->data.cbegin(), sector->data.size()); } } } diff --git a/lib/macintosh/decoder.cc b/lib/macintosh/decoder.cc index 3701e0b0..53376083 100644 --- a/lib/macintosh/decoder.cc +++ b/lib/macintosh/decoder.cc @@ -12,7 +12,8 @@ #include #include -const FluxPattern SECTOR_ID_PATTERN(16, 0xd5aa); +const FluxPattern SECTOR_RECORD_PATTERN(24, MAC_SECTOR_RECORD); +const FluxPatterns SECTOR_OR_DATA_RECORD_PATTERN(24, { MAC_SECTOR_RECORD, MAC_DATA_RECORD }); static int decode_data_gcr(uint8_t gcr) { @@ -122,72 +123,57 @@ uint8_t decode_side(uint8_t side) return !!(side & 0x40); } -void MacintoshDecoder::decodeToSectors(Track& track) +nanoseconds_t MacintoshDecoder::findSector(FluxmapReader& fmr, Track& track) { - Sector sector; - sector.physicalSide = track.physicalSide; - sector.physicalTrack = track.physicalTrack; - RawRecord record; - - FluxmapReader fmr(*track.fluxmap); - - bool headerIsValid = false; - for (;;) - { - nanoseconds_t clockPeriod = fmr.seekToPattern(SECTOR_ID_PATTERN); - if (fmr.eof() || !clockPeriod) - break; - sector.clock = record.clock = clockPeriod; - sector.position = record.position = fmr.tellNs(); - - Bytes idbytes = toBytes(fmr.readRawBits(24, clockPeriod)).slice(0, 3); - record.bytes.clear().writer() += idbytes; - switch (idbytes.reader().read_be24()) - { - case MAC_SECTOR_RECORD: - { - auto header = toBytes(fmr.readRawBits(7*8, clockPeriod)) - .slice(0, 7); - record.bytes.writer().seekToEnd() += header; - - uint8_t encodedTrack = decode_data_gcr(header[0]); - if (encodedTrack != (track.physicalTrack & 0x3f)) - break; - - uint8_t encodedSector = decode_data_gcr(header[1]); - uint8_t encodedSide = decode_data_gcr(header[2]); - uint8_t formatByte = decode_data_gcr(header[3]); - uint8_t wantedsum = decode_data_gcr(header[4]); - - uint8_t gotsum = (encodedTrack ^ encodedSector ^ encodedSide ^ formatByte) & 0x3f; - headerIsValid = (wantedsum == gotsum); - sector.logicalTrack = track.physicalTrack; - sector.logicalSide = decode_side(encodedSide); - sector.logicalSector = encodedSector; - break; - } - - case MAC_DATA_RECORD: - { - if (!headerIsValid) - break; - headerIsValid = false; - - fmr.readRawBits(8, clockPeriod); /* skip spare byte */ - auto inputbuffer = toBytes(fmr.readRawBits(MAC_ENCODED_SECTOR_LENGTH*8, clockPeriod)) - .slice(0, MAC_ENCODED_SECTOR_LENGTH); - record.bytes.writer().seekToEnd() += inputbuffer; - - for (unsigned i=0; irawrecords) { - std::cout << fmt::format("I+{:.2f}us", record.clock / 1000.0) + std::cout << fmt::format("I+{:.2f}us", record.position.ns() / 1000.0) << std::endl; - hexdump(std::cout, record.bytes); + hexdump(std::cout, record.data); std::cout << std::endl; } } diff --git a/lib/record.h b/lib/record.h index e4fd6568..da3cf6a9 100644 --- a/lib/record.h +++ b/lib/record.h @@ -1,20 +1,18 @@ #ifndef RECORD_H #define RECORD_H +#include "fluxmap.h" + class RawRecord { public: RawRecord() {} - RawRecord(nanoseconds_t position, nanoseconds_t clock, const Bytes& bytes): - position(position), - clock(clock), - bytes(bytes) - {} - - nanoseconds_t position; - nanoseconds_t clock; - Bytes bytes; + Fluxmap::Position position; + nanoseconds_t clock = 0; + int physicalTrack = 0; + int physicalSide = 0; + Bytes data; }; #endif diff --git a/lib/sector.cc b/lib/sector.cc index 0378629d..e72f292d 100644 --- a/lib/sector.cc +++ b/lib/sector.cc @@ -9,6 +9,7 @@ const std::string Sector::statusToString(Status status) case Status::OK: return "OK"; case Status::BAD_CHECKSUM: return "bad checksum"; case Status::MISSING: return "sector not found"; + case Status::DATA_MISSING: return "present but no data found"; case Status::CONFLICT: return "conflicting data"; default: return fmt::format("unknown error {}", status); } diff --git a/lib/sector.h b/lib/sector.h index 0c415b4e..298646b1 100644 --- a/lib/sector.h +++ b/lib/sector.h @@ -2,6 +2,7 @@ #define SECTOR_H #include "bytes.h" +#include "fluxmap.h" /* * Note that sectors here used zero-based numbering throughout (to make the @@ -16,6 +17,7 @@ public: OK, BAD_CHECKSUM, MISSING, + DATA_MISSING, CONFLICT, INTERNAL_ERROR }; @@ -23,7 +25,7 @@ public: static const std::string statusToString(Status status); Status status = Status::INTERNAL_ERROR; - nanoseconds_t position = 0; + Fluxmap::Position position; nanoseconds_t clock = 0; int physicalTrack = 0; int physicalSide = 0; diff --git a/lib/victor9k/victor9k.h b/lib/victor9k/victor9k.h index fa7cb92d..dbbb3689 100644 --- a/lib/victor9k/victor9k.h +++ b/lib/victor9k/victor9k.h @@ -9,7 +9,7 @@ class Sector; class Fluxmap; -class Victor9kDecoder : public AbstractSoftSectorDecoder +class Victor9kDecoder : public AbstractStatefulDecoder { public: virtual ~Victor9kDecoder() {} diff --git a/src/fe-inspect.cc b/src/fe-inspect.cc index a74a1c0d..1564c257 100644 --- a/src/fe-inspect.cc +++ b/src/fe-inspect.cc @@ -53,6 +53,8 @@ int main(int argc, const char* argv[]) nanoseconds_t clockPeriod = track->fluxmap->guessClock(); std::cout << fmt::format(" {:.2f} us clock detected; ", (double)clockPeriod/1000.0) << std::flush; + FluxmapReader fmr(*track->fluxmap); +#if 0 clockPeriod *= clockScaleFlag; std::cout << fmt::format("{:.2f} us bit clock; ", (double)clockPeriod/1000.0) << std::flush; @@ -116,23 +118,24 @@ int main(int argc, const char* argv[]) lasttransition = transition; } } +#endif if (dumpBitstreamFlag) { - std::cout << "Aligned bitstream of length " << bitmap.size() - << " follows:" << std::endl - << std::endl; + fmr.seek(seekFlag*1000000.0); - size_t cursor = seekFlag*1000000.0 / clockPeriod; - while (cursor < bitmap.size()) + std::cout << fmt::format("Aligned bitstream from {:.3f}ms follows:\n", + fmr.tell().ns() / 1000000.0); + + while (!fmr.eof()) { - std::cout << fmt::format("{: 10.3f} : ", (double)cursor / clockPeriod); + std::cout << fmt::format("{: 10.3f} : ", fmr.tell().ns() / 1000000.0); for (unsigned i=0; i<60; i++) { - if (cursor >= bitmap.size()) + if (fmr.eof()) break; - std::cout << (bitmap[cursor] ? 'X' : '-'); - cursor++; + bool b = fmr.readRawBit(clockPeriod); + std::cout << (b ? 'X' : '-'); } std::cout << std::endl; diff --git a/src/fe-readfb100.cc b/src/fe-readfb100.cc index a8aa7d32..e50da488 100644 --- a/src/fe-readfb100.cc +++ b/src/fe-readfb100.cc @@ -17,7 +17,7 @@ static StringFlag outputFilename( int main(int argc, const char* argv[]) { - setReaderDefaultSource(":t=0-79:s=0"); + setReaderDefaultSource(":t=0-79x2:s=0"); setReaderRevolutions(2); setDecoderManualClockRate(4.0); Flag::parseFlags(argc, argv); diff --git a/tests/fluxpattern.cc b/tests/fluxpattern.cc index 407d4d88..61f0abfb 100644 --- a/tests/fluxpattern.cc +++ b/tests/fluxpattern.cc @@ -5,46 +5,46 @@ typedef std::vector ivector; -static void test_patternconstruction() +void test_patternconstruction() { { FluxPattern fp(16, 0x0003); - assert(fp.bits == 16); - assert(fp.intervals == ivector{ 1 }); + assert(fp._bits == 16); + assert(fp._intervals == ivector{ 1 }); } { FluxPattern fp(16, 0xc000); - assert(fp.bits == 16); - assert(fp.intervals == ivector{ 1 }); + assert(fp._bits == 16); + assert(fp._intervals == ivector{ 1 }); } { FluxPattern fp(16, 0x0050); - assert(fp.bits == 16); - assert(fp.intervals == ivector{ 2 }); + assert(fp._bits == 16); + assert(fp._intervals == ivector{ 2 }); } { FluxPattern fp(16, 0x0070); - assert(fp.bits == 16); - assert((fp.intervals == ivector{ 1, 1 })); + assert(fp._bits == 16); + assert((fp._intervals == ivector{ 1, 1 })); } { FluxPattern fp(16, 0x0070); - assert(fp.bits == 16); - assert((fp.intervals == ivector{ 1, 1 })); + assert(fp._bits == 16); + assert((fp._intervals == ivector{ 1, 1 })); } { FluxPattern fp(16, 0x0110); - assert(fp.bits == 16); - assert((fp.intervals == ivector{ 4 })); + assert(fp._bits == 16); + assert((fp._intervals == ivector{ 4 })); } } -static void test_patternmatching() +void test_patternmatching() { FluxPattern fp(16, 0x000b); const unsigned matching[] = { 100, 100, 200, 100 }; @@ -59,11 +59,21 @@ static void test_patternmatching() assert(fp.matches(&closematch2[4], clock)); } +void test_patternsmatching() +{ + FluxPatterns fp(16, { 0x000b, 0x0015 }); + const unsigned matching1[] = { 100, 100, 200, 100 }; + const unsigned matching2[] = { 100, 100, 200, 200 }; + + double clock; + assert(fp.matches(&matching1[4], clock)); + assert(fp.matches(&matching2[4], clock)); +} + int main(int argc, const char* argv[]) { test_patternconstruction(); test_patternmatching(); + test_patternsmatching(); return 0; } - -