From cf9730fbb3e9f79a515403bd0507457e928a0ef9 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 9 Mar 2019 12:19:28 +0100 Subject: [PATCH] Splitting by hard sectors works, up to a point; we can correctly decode (with CRC checking!) most of the Zilog MCS disk. However, we're still stumped by the extra index hole. --- lib/crc.cc | 3 +-- lib/crc.h | 5 ++++- lib/decoders/decoders.cc | 10 +++++++--- lib/decoders/decoders.h | 6 +++++- lib/decoders/fmmfm.cc | 13 ++++++++----- lib/fluxmap.h | 3 +++ lib/globals.h | 1 + lib/hexdump.cc | 8 ++++++++ lib/zilogmcz/decoder.cc | 42 ++++++++++++++++++++++++++++++++-------- 9 files changed, 71 insertions(+), 20 deletions(-) diff --git a/lib/crc.cc b/lib/crc.cc index f04054cc..a6202701 100644 --- a/lib/crc.cc +++ b/lib/crc.cc @@ -22,11 +22,10 @@ uint8_t xorBytes(const Bytes& bytes) return i; } -uint16_t crc16(uint16_t poly, const Bytes& bytes) +uint16_t crc16(uint16_t poly, uint16_t crc, const Bytes& bytes) { ByteReader br(bytes); - uint16_t crc = 0xffff; while (!br.eof()) { crc ^= br.read_8() << 8; diff --git a/lib/crc.h b/lib/crc.h index 6bd4487f..37d77045 100644 --- a/lib/crc.h +++ b/lib/crc.h @@ -8,9 +8,12 @@ extern uint16_t sumBytes(const Bytes& bytes); extern uint8_t xorBytes(const Bytes& bytes); -extern uint16_t crc16(uint16_t poly, const Bytes& bytes); +extern uint16_t crc16(uint16_t poly, uint16_t init, const Bytes& bytes); extern uint16_t crc16ref(uint16_t poly, const Bytes& bytes); extern uint32_t crcbrother(const Bytes& bytes); +static inline uint16_t crc16(uint16_t poly, const Bytes& bytes) +{ return crc16(poly, 0xffff, bytes); } + #endif diff --git a/lib/decoders/decoders.cc b/lib/decoders/decoders.cc index aed66930..5505a7d9 100644 --- a/lib/decoders/decoders.cc +++ b/lib/decoders/decoders.cc @@ -170,13 +170,17 @@ const RawBits Fluxmap::decodeToBits(nanoseconds_t clockPeriod) const FluxmapReader fr(*this); for (;;) { - while (timestamp < lowerThreshold) + for (;;) { unsigned interval; - int opcode = fr.readPulse(interval); + int opcode = fr.read(interval); + timestamp += interval * NS_PER_TICK; if (opcode == -1) goto abort; - timestamp += interval * NS_PER_TICK; + else if ((opcode == 0x80) && (timestamp >= lowerThreshold)) + break; + else if (opcode == 0x81) + indices->push_back(count); } int clocks = (timestamp + clockPeriod/2) / clockPeriod; diff --git a/lib/decoders/decoders.h b/lib/decoders/decoders.h index 76c3181d..d416c13b 100644 --- a/lib/decoders/decoders.h +++ b/lib/decoders/decoders.h @@ -11,7 +11,11 @@ class RawBits; typedef std::vector> RawRecordVector; typedef std::vector> SectorVector; -extern Bytes decodeFmMfm(const std::vector bits); +extern Bytes decodeFmMfm(std::vector::const_iterator start, + std::vector::const_iterator end); + +static inline Bytes decodeFmMfm(const std::vector bits) +{ return decodeFmMfm(bits.begin(), bits.end()); } class AbstractDecoder { diff --git a/lib/decoders/fmmfm.cc b/lib/decoders/fmmfm.cc index 31ebac15..0b430ac0 100644 --- a/lib/decoders/fmmfm.cc +++ b/lib/decoders/fmmfm.cc @@ -1,7 +1,8 @@ #include "globals.h" #include "decoders.h" -Bytes decodeFmMfm(const std::vector bits) +Bytes decodeFmMfm( + std::vector::const_iterator ii, std::vector::const_iterator end) { /* * FM is dumb as rocks, consisting on regular clock pulses with data pulses in @@ -24,14 +25,16 @@ Bytes decodeFmMfm(const std::vector bits) Bytes bytes; ByteWriter bw(bytes); - size_t cursor = 1; int bitcount = 0; uint8_t fifo; - while (cursor < bits.size()) + while (ii != end) { - fifo = (fifo<<1) | bits[cursor]; - cursor += 2; + ii++; /* skip clock bit */ + if (ii == end) + break; + fifo = (fifo<<1) | *ii++; + bitcount++; if (bitcount == 8) { diff --git a/lib/fluxmap.h b/lib/fluxmap.h index a48eed7b..e0c04df4 100644 --- a/lib/fluxmap.h +++ b/lib/fluxmap.h @@ -59,6 +59,9 @@ public: void rewind() { _cursor = 0; } + size_t tell() const + { return _cursor; } + int read(unsigned& ticks); int readPulse(unsigned& ticks); diff --git a/lib/globals.h b/lib/globals.h index 7c175283..65313240 100644 --- a/lib/globals.h +++ b/lib/globals.h @@ -17,6 +17,7 @@ class Bytes; extern double getCurrentTime(); extern void hexdump(std::ostream& stream, const Bytes& bytes); +extern void hexdumpForSrp16(std::ostream& stream, const Bytes& bytes); class Error { diff --git a/lib/hexdump.cc b/lib/hexdump.cc index a0bf642a..8cd946c0 100644 --- a/lib/hexdump.cc +++ b/lib/hexdump.cc @@ -31,3 +31,11 @@ void hexdump(std::ostream& stream, const Bytes& buffer) } } +void hexdumpForSrp16(std::ostream& stream, const Bytes& buffer) +{ + for (uint8_t byte : buffer) + stream << fmt::format("{:02x}", byte); + stream << std::endl; +} + + diff --git a/lib/zilogmcz/decoder.cc b/lib/zilogmcz/decoder.cc index 1b37fc0a..3f84046d 100644 --- a/lib/zilogmcz/decoder.cc +++ b/lib/zilogmcz/decoder.cc @@ -6,27 +6,53 @@ #include "sector.h" #include "zilogmcz.h" #include "bytes.h" +#include "crc.h" #include "fmt/format.h" #include #include +static std::vector::const_iterator find_start_of_data(const std::vector& rawbits) +{ + uint8_t fifo = 0; + auto ii = rawbits.begin(); + + while (ii != rawbits.end()) + { + fifo = (fifo << 1) | *ii++; + if (fifo == 0xab) + return ii-2; + } + + return ii; +} + SectorVector ZilogMczDecoder::decodeToSectors( const RawRecordVector& rawRecords, unsigned physicalTrack) { std::vector> sectors; - int nextSector; - int nextSide; - bool headerIsValid = false; for (auto& rawrecord : rawRecords) { - const std::vector& rawdata = rawrecord->data; + auto start = find_start_of_data(rawrecord->data); + auto rawbytes = decodeFmMfm(start, rawrecord->data.cend()); + if (rawbytes.size() < 134) + continue; - auto ii = rawdata.cbegin()+15; - std::vector sliceddata(ii, ii+(0xa0*8*2)); - auto reversed = reverseBits(sliceddata); - const auto rawbytes = decodeFmMfm(reversed); + uint8_t sectorid = rawbytes[0] & 0x1f; + uint8_t track = rawbytes[1] & 0x7f; + if (sectorid > 31) + continue; + if (track > 80) + continue; + Bytes payload = rawbytes.slice(2, 132); + uint16_t wantChecksum = rawbytes.reader().seek(134).read_be16(); + uint16_t gotChecksum = crc16(MODBUS_POLY, 0x0000, rawbytes.slice(0, 134)); + + int status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM; + auto sector = std::unique_ptr( + new Sector(status, track, 0, sectorid, payload)); + sectors.push_back(std::move(sector)); } return sectors;