1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +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:
Thomas Harte 2017-09-24 20:07:56 -04:00
parent f789ee4ff0
commit 2a08bd9ecc
17 changed files with 287 additions and 142 deletions

View File

@ -7,7 +7,7 @@
//
#include "1770.hpp"
#include "../../Storage/Disk/Encodings/MFM.hpp"
#include "../../Storage/Disk/Encodings/MFM/MFM.hpp"
using namespace WD;

View File

@ -7,7 +7,7 @@
//
#include "i8272.hpp"
#include "../../Storage/Disk/Encodings/MFM.hpp"
#include "../../Storage/Disk/Encodings/MFM/MFM.hpp"
#include <cstdio>

View File

@ -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 */,

View File

@ -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>

View File

@ -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;

View File

@ -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) {

View File

@ -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_;

View File

@ -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;

View File

@ -8,7 +8,7 @@
#include "CPCDSK.hpp"
#include "../../Encodings/MFM.hpp"
#include "../../Encodings/MFM/MFM.hpp"
using namespace Storage::Disk;

View File

@ -9,7 +9,7 @@
#include "OricMFMDSK.hpp"
#include "../../Track/PCMTrack.hpp"
#include "../../Encodings/MFM.hpp"
#include "../../Encodings/MFM/MFM.hpp"
using namespace Storage::Disk;

View File

@ -8,7 +8,7 @@
#include "SSD.hpp"
#include "../../Encodings/MFM.hpp"
#include "../../Encodings/MFM/MFM.hpp"
using namespace Storage::Disk;

View 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 */

View File

@ -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>

View File

@ -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.

View 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));
}

View 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 */

View File

@ -8,7 +8,7 @@
#include "CPM.hpp"
#include "../Encodings/MFM.hpp"
#include "../Encodings/MFM/MFM.hpp"
using namespace Storage::Disk::CPM;