mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 15:31:09 +00:00
Factors shifting plus stateful [M]FM token recognition out of the MFMDiskController.
Given the proliferation of MFM-related classes, establishes a subdirectory for them.
This commit is contained in:
parent
f789ee4ff0
commit
2a08bd9ecc
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#include "1770.hpp"
|
||||
#include "../../Storage/Disk/Encodings/MFM.hpp"
|
||||
#include "../../Storage/Disk/Encodings/MFM/MFM.hpp"
|
||||
|
||||
using namespace WD;
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#include "i8272.hpp"
|
||||
#include "../../Storage/Disk/Encodings/MFM.hpp"
|
||||
#include "../../Storage/Disk/Encodings/MFM/MFM.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
@ -94,6 +94,8 @@
|
||||
4B69FB441C4D941400B5F0AA /* TapeUEF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B69FB421C4D941400B5F0AA /* TapeUEF.cpp */; };
|
||||
4B69FB461C4D950F00B5F0AA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; };
|
||||
4B6A4C991F58F09E00E3F787 /* 6502Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */; };
|
||||
4B7136861F78724F008B8ED9 /* MFM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136841F78724F008B8ED9 /* MFM.cpp */; };
|
||||
4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7136871F78725F008B8ED9 /* Shifter.cpp */; };
|
||||
4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7913CA1DFCD80E00175A82 /* Video.cpp */; };
|
||||
4B79E4441E3AF38600141F11 /* cassette.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4411E3AF38600141F11 /* cassette.png */; };
|
||||
4B79E4451E3AF38600141F11 /* floppy35.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B79E4421E3AF38600141F11 /* floppy35.png */; };
|
||||
@ -448,7 +450,6 @@
|
||||
4BEF6AAA1D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF6AA91D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm */; };
|
||||
4BEF6AAC1D35D1C400E73575 /* DPLLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */; };
|
||||
4BF1354C1D6D2C300054B2EA /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1354A1D6D2C300054B2EA /* StaticAnalyser.cpp */; };
|
||||
4BF8295D1D8F048B001BAE39 /* MFM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8295B1D8F048B001BAE39 /* MFM.cpp */; };
|
||||
4BF829661D8F732B001BAE39 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF829641D8F732B001BAE39 /* Disk.cpp */; };
|
||||
4BFCA1241ECBDCB400AC40C1 /* AllRAMProcessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */; };
|
||||
4BFCA1271ECBE33200AC40C1 /* TestMachineZ80.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA1261ECBE33200AC40C1 /* TestMachineZ80.mm */; };
|
||||
@ -647,6 +648,11 @@
|
||||
4B6A4C911F58F09E00E3F787 /* 6502AllRAM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502AllRAM.cpp; sourceTree = "<group>"; };
|
||||
4B6A4C921F58F09E00E3F787 /* 6502AllRAM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6502AllRAM.hpp; sourceTree = "<group>"; };
|
||||
4B6A4C951F58F09E00E3F787 /* 6502Base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 6502Base.cpp; sourceTree = "<group>"; };
|
||||
4B7136841F78724F008B8ED9 /* MFM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MFM.cpp; sourceTree = "<group>"; };
|
||||
4B7136851F78724F008B8ED9 /* MFM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MFM.hpp; sourceTree = "<group>"; };
|
||||
4B7136871F78725F008B8ED9 /* Shifter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Shifter.cpp; sourceTree = "<group>"; };
|
||||
4B7136881F78725F008B8ED9 /* Shifter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Shifter.hpp; sourceTree = "<group>"; };
|
||||
4B71368A1F787349008B8ED9 /* Constants.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Constants.hpp; sourceTree = "<group>"; };
|
||||
4B77069C1EC904570053B588 /* Z80.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Z80.hpp; path = Z80/Z80.hpp; sourceTree = "<group>"; };
|
||||
4B7913CA1DFCD80E00175A82 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Video.cpp; path = Electron/Video.cpp; sourceTree = "<group>"; };
|
||||
4B7913CB1DFCD80E00175A82 /* Video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Video.hpp; path = Electron/Video.hpp; sourceTree = "<group>"; };
|
||||
@ -1094,8 +1100,6 @@
|
||||
4BF4A2D91F534DB300B171F4 /* TargetPlatforms.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TargetPlatforms.hpp; sourceTree = "<group>"; };
|
||||
4BF4A2DA1F5365C600B171F4 /* CSZX8081+Instantiation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CSZX8081+Instantiation.h"; sourceTree = "<group>"; };
|
||||
4BF6606A1F281573002CB053 /* ClockReceiver.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ClockReceiver.hpp; sourceTree = "<group>"; };
|
||||
4BF8295B1D8F048B001BAE39 /* MFM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MFM.cpp; path = Encodings/MFM.cpp; sourceTree = "<group>"; };
|
||||
4BF8295C1D8F048B001BAE39 /* MFM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = MFM.hpp; path = Encodings/MFM.hpp; sourceTree = "<group>"; };
|
||||
4BF8295F1D8F3C87001BAE39 /* CRC.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CRC.hpp; path = ../../NumberTheory/CRC.hpp; sourceTree = "<group>"; };
|
||||
4BF829641D8F732B001BAE39 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Disk.cpp; path = ../../StaticAnalyser/Acorn/Disk.cpp; sourceTree = "<group>"; };
|
||||
4BF829651D8F732B001BAE39 /* Disk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Disk.hpp; path = ../../StaticAnalyser/Acorn/Disk.hpp; sourceTree = "<group>"; };
|
||||
@ -1651,6 +1655,19 @@
|
||||
path = Implementation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B7136831F78724F008B8ED9 /* MFM */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B7136841F78724F008B8ED9 /* MFM.cpp */,
|
||||
4B7136851F78724F008B8ED9 /* MFM.hpp */,
|
||||
4B7136871F78725F008B8ED9 /* Shifter.cpp */,
|
||||
4B7136881F78725F008B8ED9 /* Shifter.hpp */,
|
||||
4B71368A1F787349008B8ED9 /* Constants.hpp */,
|
||||
);
|
||||
name = MFM;
|
||||
path = Encodings/MFM;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B77069E1EC9045B0053B588 /* Z80 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2018,10 +2035,9 @@
|
||||
4BB697CF1D4BA44900248BDF /* Encodings */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B7136831F78724F008B8ED9 /* MFM */,
|
||||
4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */,
|
||||
4BB697CD1D4BA44400248BDF /* CommodoreGCR.hpp */,
|
||||
4BF8295B1D8F048B001BAE39 /* MFM.cpp */,
|
||||
4BF8295C1D8F048B001BAE39 /* MFM.hpp */,
|
||||
);
|
||||
name = Encodings;
|
||||
sourceTree = "<group>";
|
||||
@ -2853,6 +2869,7 @@
|
||||
4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */,
|
||||
4B59199C1DAC6C46005BB85C /* OricTAP.cpp in Sources */,
|
||||
4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */,
|
||||
4B7136861F78724F008B8ED9 /* MFM.cpp in Sources */,
|
||||
4B448E841F1C4C480009ABD6 /* PulseQueuedTape.cpp in Sources */,
|
||||
4BD14B111D74627C0088EAD6 /* StaticAnalyser.cpp in Sources */,
|
||||
4BBF99151C8FBA6F0075DAFB /* CRTOpenGL.cpp in Sources */,
|
||||
@ -2908,7 +2925,6 @@
|
||||
4B8334841F5DA0360097E338 /* Z80Storage.cpp in Sources */,
|
||||
4BA61EB01D91515900B3C876 /* NSData+StdVector.mm in Sources */,
|
||||
4B4DC8211D2C2425003C5BF8 /* Vic20.cpp in Sources */,
|
||||
4BF8295D1D8F048B001BAE39 /* MFM.cpp in Sources */,
|
||||
4BE77A2E1D84ADFB00BC3827 /* File.cpp in Sources */,
|
||||
4B14978B1EE4AC5E00CE2596 /* StaticAnalyser.cpp in Sources */,
|
||||
4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */,
|
||||
@ -2955,6 +2971,7 @@
|
||||
4BEA52661DF3472B007E74F2 /* Speaker.cpp in Sources */,
|
||||
4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */,
|
||||
4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */,
|
||||
4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */,
|
||||
4BC3B7521CD1956900F86E85 /* OutputShader.cpp in Sources */,
|
||||
4B5073071DDD3B9400C48FBD /* ArrayBuilder.cpp in Sources */,
|
||||
4BEE0A6F1D72496600532C7B /* Cartridge.cpp in Sources */,
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "Disk.hpp"
|
||||
#include "../../Storage/Disk/Controller/DiskController.hpp"
|
||||
#include "../../Storage/Disk/Encodings/MFM.hpp"
|
||||
#include "../../Storage/Disk/Encodings/MFM/MFM.hpp"
|
||||
#include "../../NumberTheory/CRC.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "StaticAnalyser.hpp"
|
||||
|
||||
#include "../../Storage/Disk/Parsers/CPM.hpp"
|
||||
#include "../../Storage/Disk/Encodings/MFM.hpp"
|
||||
#include "../../Storage/Disk/Encodings/MFM/MFM.hpp"
|
||||
|
||||
static bool strcmp_insensitive(const char *a, const char *b) {
|
||||
if(strlen(a) != strlen(b)) return false;
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "MFMDiskController.hpp"
|
||||
|
||||
#include "../Encodings/MFM.hpp"
|
||||
#include "../Encodings/MFM/MFM.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
@ -16,7 +16,7 @@ MFMController::MFMController(Cycles clock_rate) :
|
||||
Storage::Disk::Controller(clock_rate),
|
||||
crc_generator_(0x1021, 0xffff),
|
||||
data_mode_(DataMode::Scanning),
|
||||
is_awaiting_marker_value_(false) {
|
||||
shifter_(&crc_generator_) {
|
||||
}
|
||||
|
||||
void MFMController::process_index_hole() {
|
||||
@ -34,7 +34,7 @@ void MFMController::set_is_double_density(bool is_double_density) {
|
||||
bit_length.clock_rate = is_double_density ? 500000 : 250000;
|
||||
set_expected_bit_length(bit_length);
|
||||
|
||||
if(!is_double_density) is_awaiting_marker_value_ = false;
|
||||
shifter_.set_is_double_density(is_double_density);
|
||||
}
|
||||
|
||||
bool MFMController::get_is_double_density() {
|
||||
@ -43,6 +43,7 @@ bool MFMController::get_is_double_density() {
|
||||
|
||||
void MFMController::set_data_mode(DataMode mode) {
|
||||
data_mode_ = mode;
|
||||
shifter_.set_should_obey_syncs(mode == DataMode::Scanning);
|
||||
}
|
||||
|
||||
MFMController::Token MFMController::get_latest_token() {
|
||||
@ -56,102 +57,32 @@ NumberTheory::CRC16 &MFMController::get_crc_generator() {
|
||||
void MFMController::process_input_bit(int value) {
|
||||
if(data_mode_ == DataMode::Writing) return;
|
||||
|
||||
shift_register_ = (shift_register_ << 1) | value;
|
||||
bits_since_token_++;
|
||||
|
||||
if(data_mode_ == DataMode::Scanning) {
|
||||
Token::Type token_type = Token::Byte;
|
||||
if(!is_double_density_) {
|
||||
switch(shift_register_ & 0xffff) {
|
||||
case Storage::Encodings::MFM::FMIndexAddressMark:
|
||||
token_type = Token::Index;
|
||||
crc_generator_.reset();
|
||||
crc_generator_.add(latest_token_.byte_value = Storage::Encodings::MFM::IndexAddressByte);
|
||||
break;
|
||||
case Storage::Encodings::MFM::FMIDAddressMark:
|
||||
token_type = Token::ID;
|
||||
crc_generator_.reset();
|
||||
crc_generator_.add(latest_token_.byte_value = Storage::Encodings::MFM::IDAddressByte);
|
||||
break;
|
||||
case Storage::Encodings::MFM::FMDataAddressMark:
|
||||
token_type = Token::Data;
|
||||
crc_generator_.reset();
|
||||
crc_generator_.add(latest_token_.byte_value = Storage::Encodings::MFM::DataAddressByte);
|
||||
break;
|
||||
case Storage::Encodings::MFM::FMDeletedDataAddressMark:
|
||||
token_type = Token::DeletedData;
|
||||
crc_generator_.reset();
|
||||
crc_generator_.add(latest_token_.byte_value = Storage::Encodings::MFM::DeletedDataAddressByte);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(shift_register_ & 0xffff) {
|
||||
case Storage::Encodings::MFM::MFMIndexSync:
|
||||
bits_since_token_ = 0;
|
||||
is_awaiting_marker_value_ = true;
|
||||
|
||||
token_type = Token::Sync;
|
||||
latest_token_.byte_value = Storage::Encodings::MFM::MFMIndexSyncByteValue;
|
||||
break;
|
||||
case Storage::Encodings::MFM::MFMSync:
|
||||
bits_since_token_ = 0;
|
||||
is_awaiting_marker_value_ = true;
|
||||
crc_generator_.set_value(Storage::Encodings::MFM::MFMPostSyncCRCValue);
|
||||
|
||||
token_type = Token::Sync;
|
||||
latest_token_.byte_value = Storage::Encodings::MFM::MFMSyncByteValue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(token_type != Token::Byte) {
|
||||
latest_token_.type = token_type;
|
||||
bits_since_token_ = 0;
|
||||
posit_event((int)Event::Token);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(bits_since_token_ == 16) {
|
||||
latest_token_.type = Token::Byte;
|
||||
latest_token_.byte_value = (uint8_t)(
|
||||
((shift_register_ & 0x0001) >> 0) |
|
||||
((shift_register_ & 0x0004) >> 1) |
|
||||
((shift_register_ & 0x0010) >> 2) |
|
||||
((shift_register_ & 0x0040) >> 3) |
|
||||
((shift_register_ & 0x0100) >> 4) |
|
||||
((shift_register_ & 0x0400) >> 5) |
|
||||
((shift_register_ & 0x1000) >> 6) |
|
||||
((shift_register_ & 0x4000) >> 7));
|
||||
bits_since_token_ = 0;
|
||||
|
||||
if(is_awaiting_marker_value_ && is_double_density_) {
|
||||
is_awaiting_marker_value_ = false;
|
||||
switch(latest_token_.byte_value) {
|
||||
case Storage::Encodings::MFM::IndexAddressByte:
|
||||
latest_token_.type = Token::Index;
|
||||
break;
|
||||
case Storage::Encodings::MFM::IDAddressByte:
|
||||
latest_token_.type = Token::ID;
|
||||
break;
|
||||
case Storage::Encodings::MFM::DataAddressByte:
|
||||
latest_token_.type = Token::Data;
|
||||
break;
|
||||
case Storage::Encodings::MFM::DeletedDataAddressByte:
|
||||
latest_token_.type = Token::DeletedData;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
crc_generator_.add(latest_token_.byte_value);
|
||||
posit_event((int)Event::Token);
|
||||
shifter_.add_input_bit(value);
|
||||
switch(shifter_.get_token()) {
|
||||
case Encodings::MFM::Shifter::Token::None:
|
||||
return;
|
||||
|
||||
case Encodings::MFM::Shifter::Token::Index:
|
||||
latest_token_.type = Token::Index;
|
||||
break;
|
||||
case Encodings::MFM::Shifter::Token::ID:
|
||||
latest_token_.type = Token::ID;
|
||||
break;
|
||||
case Encodings::MFM::Shifter::Token::Data:
|
||||
latest_token_.type = Token::Data;
|
||||
break;
|
||||
case Encodings::MFM::Shifter::Token::DeletedData:
|
||||
latest_token_.type = Token::DeletedData;
|
||||
break;
|
||||
case Encodings::MFM::Shifter::Token::Sync:
|
||||
latest_token_.type = Token::Sync;
|
||||
break;
|
||||
case Encodings::MFM::Shifter::Token::Byte:
|
||||
latest_token_.type = Token::Byte;
|
||||
break;
|
||||
}
|
||||
latest_token_.byte_value = shifter_.get_byte();
|
||||
posit_event((int)Event::Token);
|
||||
}
|
||||
|
||||
void MFMController::write_bit(int bit) {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "DiskController.hpp"
|
||||
#include "../../../NumberTheory/CRC.hpp"
|
||||
#include "../../../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "../Encodings/MFM/Shifter.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Disk {
|
||||
@ -150,18 +151,14 @@ class MFMController: public Controller {
|
||||
virtual void process_index_hole();
|
||||
virtual void process_write_completed();
|
||||
|
||||
// PLL input state
|
||||
int bits_since_token_;
|
||||
int shift_register_;
|
||||
bool is_awaiting_marker_value_;
|
||||
// Reading state.
|
||||
Token latest_token_;
|
||||
Encodings::MFM::Shifter shifter_;
|
||||
|
||||
// input configuration
|
||||
bool is_double_density_;
|
||||
DataMode data_mode_;
|
||||
|
||||
// output
|
||||
Token latest_token_;
|
||||
|
||||
// writing
|
||||
int last_bit_;
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "AcornADF.hpp"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "../../Encodings/MFM.hpp"
|
||||
#include "../../Encodings/MFM/MFM.hpp"
|
||||
|
||||
namespace {
|
||||
static const unsigned int sectors_per_track = 16;
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "CPCDSK.hpp"
|
||||
|
||||
#include "../../Encodings/MFM.hpp"
|
||||
#include "../../Encodings/MFM/MFM.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "OricMFMDSK.hpp"
|
||||
|
||||
#include "../../Track/PCMTrack.hpp"
|
||||
#include "../../Encodings/MFM.hpp"
|
||||
#include "../../Encodings/MFM/MFM.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "SSD.hpp"
|
||||
|
||||
#include "../../Encodings/MFM.hpp"
|
||||
#include "../../Encodings/MFM/MFM.hpp"
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
|
37
Storage/Disk/Encodings/MFM/Constants.hpp
Normal file
37
Storage/Disk/Encodings/MFM/Constants.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// Constants.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 24/09/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Constants_h
|
||||
#define Constants_h
|
||||
|
||||
namespace Storage {
|
||||
namespace Encodings {
|
||||
namespace MFM {
|
||||
|
||||
const uint8_t IndexAddressByte = 0xfc;
|
||||
const uint8_t IDAddressByte = 0xfe;
|
||||
const uint8_t DataAddressByte = 0xfb;
|
||||
const uint8_t DeletedDataAddressByte = 0xf8;
|
||||
|
||||
const uint16_t FMIndexAddressMark = 0xf77a; // data 0xfc, with clock 0xd7 => 1111 1100 with clock 1101 0111 => 1111 0111 0111 1010
|
||||
const uint16_t FMIDAddressMark = 0xf57e; // data 0xfe, with clock 0xc7 => 1111 1110 with clock 1100 0111 => 1111 0101 0111 1110
|
||||
const uint16_t FMDataAddressMark = 0xf56f; // data 0xfb, with clock 0xc7 => 1111 1011 with clock 1100 0111 => 1111 0101 0110 1111
|
||||
const uint16_t FMDeletedDataAddressMark = 0xf56a; // data 0xf8, with clock 0xc7 => 1111 1000 with clock 1100 0111 => 1111 0101 0110 1010
|
||||
|
||||
const uint16_t MFMIndexSync = 0x5224; // data 0xc2, with a missing clock at 0x0080 => 0101 0010 1010 0100 without 1000 0000
|
||||
const uint16_t MFMSync = 0x4489; // data 0xa1, with a missing clock at 0x0020 => 0100 0100 1010 1001 without 0010 0000
|
||||
const uint16_t MFMPostSyncCRCValue = 0xcdb4; // the value the CRC generator should have after encountering three 0xa1s
|
||||
|
||||
const uint8_t MFMIndexSyncByteValue = 0xc2;
|
||||
const uint8_t MFMSyncByteValue = 0xa1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Constants_h */
|
@ -8,9 +8,9 @@
|
||||
|
||||
#include "MFM.hpp"
|
||||
|
||||
#include "../Track/PCMTrack.hpp"
|
||||
#include "../SingleTrackDisk/SingleTrackDisk.hpp"
|
||||
#include "../../../NumberTheory/CRC.hpp"
|
||||
#include "../../Track/PCMTrack.hpp"
|
||||
#include "../../SingleTrackDisk/SingleTrackDisk.hpp"
|
||||
#include "../../../../NumberTheory/CRC.hpp"
|
||||
|
||||
#include <set>
|
||||
|
@ -11,31 +11,15 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "../Disk.hpp"
|
||||
#include "../Controller/DiskController.hpp"
|
||||
#include "../../../NumberTheory/CRC.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "../../Disk.hpp"
|
||||
#include "../../Controller/DiskController.hpp"
|
||||
#include "../../../../NumberTheory/CRC.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Encodings {
|
||||
namespace MFM {
|
||||
|
||||
const uint8_t IndexAddressByte = 0xfc;
|
||||
const uint8_t IDAddressByte = 0xfe;
|
||||
const uint8_t DataAddressByte = 0xfb;
|
||||
const uint8_t DeletedDataAddressByte = 0xf8;
|
||||
|
||||
const uint16_t FMIndexAddressMark = 0xf77a; // data 0xfc, with clock 0xd7 => 1111 1100 with clock 1101 0111 => 1111 0111 0111 1010
|
||||
const uint16_t FMIDAddressMark = 0xf57e; // data 0xfe, with clock 0xc7 => 1111 1110 with clock 1100 0111 => 1111 0101 0111 1110
|
||||
const uint16_t FMDataAddressMark = 0xf56f; // data 0xfb, with clock 0xc7 => 1111 1011 with clock 1100 0111 => 1111 0101 0110 1111
|
||||
const uint16_t FMDeletedDataAddressMark = 0xf56a; // data 0xf8, with clock 0xc7 => 1111 1000 with clock 1100 0111 => 1111 0101 0110 1010
|
||||
|
||||
const uint16_t MFMIndexSync = 0x5224; // data 0xc2, with a missing clock at 0x0080 => 0101 0010 1010 0100 without 1000 0000
|
||||
const uint16_t MFMSync = 0x4489; // data 0xa1, with a missing clock at 0x0020 => 0100 0100 1010 1001 without 0010 0000
|
||||
const uint16_t MFMPostSyncCRCValue = 0xcdb4; // the value the CRC generator should have after encountering three 0xa1s
|
||||
|
||||
const uint8_t MFMIndexSyncByteValue = 0xc2;
|
||||
const uint8_t MFMSyncByteValue = 0xa1;
|
||||
|
||||
/*!
|
||||
Represents a single [M]FM sector, identified by its track, side and sector records, a blob of data
|
||||
and a few extra flags of metadata.
|
120
Storage/Disk/Encodings/MFM/Shifter.cpp
Normal file
120
Storage/Disk/Encodings/MFM/Shifter.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
//
|
||||
// Shifter.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 24/09/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Shifter.hpp"
|
||||
#include "Constants.hpp"
|
||||
|
||||
using namespace Storage::Encodings::MFM;
|
||||
|
||||
Shifter::Shifter() : owned_crc_generator_(new NumberTheory::CRC16(0x1021, 0xffff)), crc_generator_(owned_crc_generator_.get()) {}
|
||||
Shifter::Shifter(NumberTheory::CRC16 *crc_generator) : crc_generator_(crc_generator) {}
|
||||
|
||||
void Shifter::set_is_double_density(bool is_double_density) {
|
||||
is_double_density_ = is_double_density;
|
||||
if(!is_double_density) is_awaiting_marker_value_ = false;
|
||||
}
|
||||
|
||||
void Shifter::set_should_obey_syncs(bool should_obey_syncs) {
|
||||
should_obey_syncs_ = should_obey_syncs;
|
||||
}
|
||||
|
||||
void Shifter::add_input_bit(int value) {
|
||||
shift_register_ = (shift_register_ << 1) | value;
|
||||
bits_since_token_++;
|
||||
|
||||
token_ = Token::None;
|
||||
if(should_obey_syncs_) {
|
||||
if(!is_double_density_) {
|
||||
switch(shift_register_ & 0xffff) {
|
||||
case Storage::Encodings::MFM::FMIndexAddressMark:
|
||||
token_ = Token::Index;
|
||||
crc_generator_->reset();
|
||||
crc_generator_->add(Storage::Encodings::MFM::IndexAddressByte);
|
||||
break;
|
||||
case Storage::Encodings::MFM::FMIDAddressMark:
|
||||
token_ = Token::ID;
|
||||
crc_generator_->reset();
|
||||
crc_generator_->add(Storage::Encodings::MFM::IDAddressByte);
|
||||
break;
|
||||
case Storage::Encodings::MFM::FMDataAddressMark:
|
||||
token_ = Token::Data;
|
||||
crc_generator_->reset();
|
||||
crc_generator_->add(Storage::Encodings::MFM::DataAddressByte);
|
||||
break;
|
||||
case Storage::Encodings::MFM::FMDeletedDataAddressMark:
|
||||
token_ = Token::DeletedData;
|
||||
crc_generator_->reset();
|
||||
crc_generator_->add(Storage::Encodings::MFM::DeletedDataAddressByte);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(shift_register_ & 0xffff) {
|
||||
case Storage::Encodings::MFM::MFMIndexSync:
|
||||
bits_since_token_ = 0;
|
||||
is_awaiting_marker_value_ = true;
|
||||
|
||||
token_ = Token::Sync;
|
||||
break;
|
||||
case Storage::Encodings::MFM::MFMSync:
|
||||
bits_since_token_ = 0;
|
||||
is_awaiting_marker_value_ = true;
|
||||
crc_generator_->set_value(Storage::Encodings::MFM::MFMPostSyncCRCValue);
|
||||
|
||||
token_ = Token::Sync;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(token_ != Token::None) {
|
||||
bits_since_token_ = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(bits_since_token_ == 16) {
|
||||
token_ = Token::Byte;
|
||||
bits_since_token_ = 0;
|
||||
|
||||
if(is_awaiting_marker_value_ && is_double_density_) {
|
||||
is_awaiting_marker_value_ = false;
|
||||
switch(get_byte()) {
|
||||
case Storage::Encodings::MFM::IndexAddressByte:
|
||||
token_ = Token::Index;
|
||||
break;
|
||||
case Storage::Encodings::MFM::IDAddressByte:
|
||||
token_ = Token::ID;
|
||||
break;
|
||||
case Storage::Encodings::MFM::DataAddressByte:
|
||||
token_ = Token::Data;
|
||||
break;
|
||||
case Storage::Encodings::MFM::DeletedDataAddressByte:
|
||||
token_ = Token::DeletedData;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
crc_generator_->add(get_byte());
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Shifter::get_byte() const {
|
||||
return (uint8_t)(
|
||||
((shift_register_ & 0x0001) >> 0) |
|
||||
((shift_register_ & 0x0004) >> 1) |
|
||||
((shift_register_ & 0x0010) >> 2) |
|
||||
((shift_register_ & 0x0040) >> 3) |
|
||||
((shift_register_ & 0x0100) >> 4) |
|
||||
((shift_register_ & 0x0400) >> 5) |
|
||||
((shift_register_ & 0x1000) >> 6) |
|
||||
((shift_register_ & 0x4000) >> 7));
|
||||
}
|
59
Storage/Disk/Encodings/MFM/Shifter.hpp
Normal file
59
Storage/Disk/Encodings/MFM/Shifter.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// Shifter.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 24/09/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Shifter_hpp
|
||||
#define Shifter_hpp
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include "../../../../NumberTheory/CRC.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Encodings {
|
||||
namespace MFM {
|
||||
|
||||
class Shifter {
|
||||
public:
|
||||
Shifter();
|
||||
Shifter(NumberTheory::CRC16 *crc_generator);
|
||||
|
||||
void set_is_double_density(bool is_double_density);
|
||||
void set_should_obey_syncs(bool should_obey_syncs);
|
||||
void add_input_bit(int bit);
|
||||
|
||||
enum Token {
|
||||
Index, ID, Data, DeletedData, Sync, Byte, None
|
||||
};
|
||||
uint8_t get_byte() const;
|
||||
Token get_token() const {
|
||||
return token_;
|
||||
}
|
||||
NumberTheory::CRC16 &get_crc_generator() {
|
||||
return *crc_generator_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Bit stream input state
|
||||
int bits_since_token_ = 0;
|
||||
int shift_register_ = 0;
|
||||
bool is_awaiting_marker_value_ = false;
|
||||
bool should_obey_syncs_;
|
||||
Token token_;
|
||||
|
||||
// input configuration
|
||||
bool is_double_density_ = false;
|
||||
|
||||
std::unique_ptr<NumberTheory::CRC16> owned_crc_generator_;
|
||||
NumberTheory::CRC16 *crc_generator_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Shifter_hpp */
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "CPM.hpp"
|
||||
|
||||
#include "../Encodings/MFM.hpp"
|
||||
#include "../Encodings/MFM/MFM.hpp"
|
||||
|
||||
using namespace Storage::Disk::CPM;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user