#include "globals.h" #include "fluxmap.h" #include "decoders/fluxmapreader.h" #include "protocol.h" #include "decoders/decoders.h" #include "sector.h" #include "victor9k.h" #include "crc.h" #include "bytes.h" #include "fmt/format.h" #include #include const FluxPattern SECTOR_RECORD_PATTERN(32, VICTOR9K_SECTOR_RECORD); const FluxPattern DATA_RECORD_PATTERN(32, VICTOR9K_DATA_RECORD); const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN }); static int decode_data_gcr(uint8_t gcr) { switch (gcr) { #define GCR_ENTRY(gcr, data) \ case gcr: return data; #include "data_gcr.h" #undef GCR_ENTRY } return -1; } static Bytes decode(const std::vector& bits) { Bytes output; ByteWriter bw(output); BitWriter bitw(bw); auto ii = bits.begin(); while (ii != bits.end()) { uint8_t inputfifo = 0; for (size_t i=0; i<5; i++) { if (ii == bits.end()) break; inputfifo = (inputfifo<<1) | *ii++; } uint8_t decoded = decode_data_gcr(inputfifo); bitw.push(decoded, 4); } bitw.flush(); return output; } class Victor9kDecoder : public AbstractDecoder { public: Victor9kDecoder(const DecoderProto& config): AbstractDecoder(config) {} RecordType advanceToNextRecord() { const FluxMatcher* matcher = nullptr; _sector->clock = _sector->bitcell = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher); if (matcher == &SECTOR_RECORD_PATTERN) return SECTOR_RECORD; if (matcher == &DATA_RECORD_PATTERN) return DATA_RECORD; return UNKNOWN_RECORD; } void decodeSectorRecord() { /* Skip the sync marker bit. */ readRawBits(22); /* Read header. */ auto bytes = decode(readRawBits(4*10)).slice(0, 4); uint8_t rawTrack = bytes[1]; _sector->logicalSector = bytes[2]; uint8_t gotChecksum = bytes[3]; _sector->logicalTrack = rawTrack & 0x7f; _sector->logicalSide = rawTrack >> 7; uint8_t wantChecksum = bytes[1] + bytes[2]; if ((_sector->logicalSector > 20) || (_sector->logicalTrack > 85) || (_sector->logicalSide > 1)) return; if (wantChecksum == gotChecksum) _sector->status = Sector::DATA_MISSING; /* unintuitive but correct */ } void decodeDataRecord() { /* Skip the sync marker bit. */ readRawBits(22); /* Read data. */ auto bytes = decode(readRawBits((VICTOR9K_SECTOR_LENGTH+5)*10)) .slice(0, VICTOR9K_SECTOR_LENGTH+5); ByteReader br(bytes); /* Check that this is actually a data record. */ if (br.read_8() != 8) return; _sector->data = br.read(VICTOR9K_SECTOR_LENGTH); uint16_t gotChecksum = sumBytes(_sector->data); uint16_t wantChecksum = br.read_le16(); _sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM; } }; std::unique_ptr createVictor9kDecoder(const DecoderProto& config) { return std::unique_ptr(new Victor9kDecoder(config)); }