1 #include "globals.h" 2 #include "decoders/decoders.h" 3 #include "aeslanier.h" 4 #include "crc.h" 5 #include "fluxmap.h" 6 #include "decoders/fluxmapreader.h" 7 #include "sector.h" 8 #include "bytes.h" 9 #include "record.h" 10 #include "fmt/format.h" 11 #include <string.h> 12 13 static const FluxPattern SECTOR_PATTERN(32, AESLANIER_RECORD_SEPARATOR); 14 15 /* This is actually M2FM, rather than MFM, but it our MFM/FM decoder copes fine with it. */ 16 reverse_bits(const Bytes & input)17static Bytes reverse_bits(const Bytes& input) 18 { 19 Bytes output; 20 ByteWriter bw(output); 21 22 for (uint8_t b : input) 23 bw.write_8(reverse_bits(b)); 24 return output; 25 } 26 advanceToNextRecord()27AbstractDecoder::RecordType AesLanierDecoder::advanceToNextRecord() 28 { 29 _sector->clock = _fmr->seekToPattern(SECTOR_PATTERN); 30 if (_fmr->eof() || !_sector->clock) 31 return UNKNOWN_RECORD; 32 return SECTOR_RECORD; 33 } 34 decodeSectorRecord()35void AesLanierDecoder::decodeSectorRecord() 36 { 37 /* Skip ID mark. */ 38 39 readRawBits(16); 40 41 const auto& rawbits = readRawBits(AESLANIER_RECORD_SIZE*16); 42 const auto& bytes = decodeFmMfm(rawbits).slice(0, AESLANIER_RECORD_SIZE); 43 const auto& reversed = reverse_bits(bytes); 44 45 _sector->logicalTrack = reversed[1]; 46 _sector->logicalSide = 0; 47 _sector->logicalSector = reversed[2]; 48 49 /* Check header 'checksum' (which seems far too simple to mean much). */ 50 51 { 52 uint8_t wanted = reversed[3]; 53 uint8_t got = reversed[1] + reversed[2]; 54 if (wanted != got) 55 return; 56 } 57 58 /* Check data checksum, which also includes the header and is 59 * significantly better. */ 60 61 _sector->data = reversed.slice(1, AESLANIER_SECTOR_LENGTH); 62 uint16_t wanted = reversed.reader().seek(0x101).read_le16(); 63 uint16_t got = crc16ref(MODBUS_POLY_REF, _sector->data); 64 _sector->status = (wanted == got) ? Sector::OK : Sector::BAD_CHECKSUM; 65 } 66