1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-19 08:31:11 +00:00

Sketched out the generic interface for a disk, documenting it and the tape interface while I'm here.

This commit is contained in:
Thomas Harte 2016-07-10 08:54:39 -04:00
parent cf83258eaf
commit 9e3d6b762b
6 changed files with 132 additions and 6 deletions

View File

@ -42,6 +42,7 @@
4B73C71A1D036BD90074D992 /* Vic20Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B73C7191D036BD90074D992 /* Vic20Document.swift */; }; 4B73C71A1D036BD90074D992 /* Vic20Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B73C7191D036BD90074D992 /* Vic20Document.swift */; };
4B73C71D1D036C030074D992 /* Vic20Document.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B73C71B1D036C030074D992 /* Vic20Document.xib */; }; 4B73C71D1D036C030074D992 /* Vic20Document.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B73C71B1D036C030074D992 /* Vic20Document.xib */; };
4B92EACA1B7C112B00246143 /* 6502TimingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */; }; 4B92EACA1B7C112B00246143 /* 6502TimingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */; };
4BAB62AD1D3272D200DF5BA0 /* Disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAB62AB1D3272D200DF5BA0 /* Disk.cpp */; };
4BB298EE1B587D8400A49093 /* 6502_functional_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E01B587D8300A49093 /* 6502_functional_test.bin */; }; 4BB298EE1B587D8400A49093 /* 6502_functional_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E01B587D8300A49093 /* 6502_functional_test.bin */; };
4BB298EF1B587D8400A49093 /* AllSuiteA.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E11B587D8300A49093 /* AllSuiteA.bin */; }; 4BB298EF1B587D8400A49093 /* AllSuiteA.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E11B587D8300A49093 /* AllSuiteA.bin */; };
4BB298F11B587D8400A49093 /* start in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E51B587D8300A49093 /* start */; }; 4BB298F11B587D8400A49093 /* start in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E51B587D8300A49093 /* start */; };
@ -415,6 +416,9 @@
4B73C7191D036BD90074D992 /* Vic20Document.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vic20Document.swift; sourceTree = "<group>"; }; 4B73C7191D036BD90074D992 /* Vic20Document.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vic20Document.swift; sourceTree = "<group>"; };
4B73C71C1D036C030074D992 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/Vic20Document.xib"; sourceTree = SOURCE_ROOT; }; 4B73C71C1D036C030074D992 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/Vic20Document.xib"; sourceTree = SOURCE_ROOT; };
4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 6502TimingTests.swift; sourceTree = "<group>"; }; 4B92EAC91B7C112B00246143 /* 6502TimingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 6502TimingTests.swift; sourceTree = "<group>"; };
4BAB62AB1D3272D200DF5BA0 /* Disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Disk.cpp; sourceTree = "<group>"; };
4BAB62AC1D3272D200DF5BA0 /* Disk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Disk.hpp; sourceTree = "<group>"; };
4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Storage.hpp; sourceTree = "<group>"; };
4BB297E01B587D8300A49093 /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = 6502_functional_test.bin; sourceTree = "<group>"; }; 4BB297E01B587D8300A49093 /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = 6502_functional_test.bin; sourceTree = "<group>"; };
4BB297E11B587D8300A49093 /* AllSuiteA.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = AllSuiteA.bin; sourceTree = "<group>"; }; 4BB297E11B587D8300A49093 /* AllSuiteA.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = AllSuiteA.bin; sourceTree = "<group>"; };
4BB297E51B587D8300A49093 /* start */ = {isa = PBXFileReference; lastKnownFileType = file; path = " start"; sourceTree = "<group>"; }; 4BB297E51B587D8300A49093 /* start */ = {isa = PBXFileReference; lastKnownFileType = file; path = " start"; sourceTree = "<group>"; };
@ -941,7 +945,9 @@
4B69FB391C4D908A00B5F0AA /* Storage */ = { 4B69FB391C4D908A00B5F0AA /* Storage */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
4BAB62AA1D3272D200DF5BA0 /* Disk */,
4B69FB3A1C4D908A00B5F0AA /* Tape */, 4B69FB3A1C4D908A00B5F0AA /* Tape */,
4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */,
); );
name = Storage; name = Storage;
path = ../../Storage; path = ../../Storage;
@ -969,6 +975,15 @@
path = Formats; path = Formats;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
4BAB62AA1D3272D200DF5BA0 /* Disk */ = {
isa = PBXGroup;
children = (
4BAB62AB1D3272D200DF5BA0 /* Disk.cpp */,
4BAB62AC1D3272D200DF5BA0 /* Disk.hpp */,
);
path = Disk;
sourceTree = "<group>";
};
4BB297E41B587D8300A49093 /* Wolfgang Lorenz 6502 test suite */ = { 4BB297E41B587D8300A49093 /* Wolfgang Lorenz 6502 test suite */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1818,6 +1833,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
4BAB62AD1D3272D200DF5BA0 /* Disk.cpp in Sources */,
4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */, 4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */,
4BBF99151C8FBA6F0075DAFB /* CRTOpenGL.cpp in Sources */, 4BBF99151C8FBA6F0075DAFB /* CRTOpenGL.cpp in Sources */,
4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */, 4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */,

9
Storage/Disk/Disk.cpp Normal file
View File

@ -0,0 +1,9 @@
//
// Disk.cpp
// Clock Signal
//
// Created by Thomas Harte on 10/07/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#include "Disk.hpp"

66
Storage/Disk/Disk.hpp Normal file
View File

@ -0,0 +1,66 @@
//
// Disk.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/07/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#ifndef Disk_hpp
#define Disk_hpp
#include <memory>
#include "../Storage.hpp"
namespace Storage {
/*!
Models a single track on a disk as a series of events, each event being of arbitrary length
and resulting in either a flux transition or the sensing of an index hole.
Subclasses should implement @c get_next_event.
*/
class Track {
public:
struct Event {
enum {
IndexHole, FluxTransition
} type;
Time length;
};
virtual Event get_next_event() = 0;
};
/*!
Models a disk as a collection of tracks, providing a range of possible track positions and allowing
a point sampling of the track beneath any of those positions (if any).
The intention is not that tracks necessarily be evenly spaced; a head_position_count of 3 wih track
A appearing in positions 0 and 1, and track B appearing in position 2 is an appropriate use of this API
if it matches the media.
The track returned is point sampled only; if a particular disk drive has a sufficiently large head to
pick up multiple tracks at once then the drive responsible for asking for multiple tracks and for
merging the results.
*/
class Disk {
public:
/*!
Returns the number of discrete positions that this disk uses to model its complete surface area.
This is not necessarily a track count. There is no implicit guarantee that every position will
return a distinct track, or if the media is holeless will return any track at all.
*/
virtual unsigned int get_head_position_count() = 0;
/*!
Returns the @c Track at @c position if there are any detectable events there; returns @c nullptr otherwise.
*/
virtual std::shared_ptr<Track> get_track_at_position(unsigned int position) = 0;
};
}
#endif /* Disk_hpp */

20
Storage/Storage.hpp Normal file
View File

@ -0,0 +1,20 @@
//
// Storage.hpp
// Clock Signal
//
// Created by Thomas Harte on 10/07/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#ifndef Storage_hpp
#define Storage_hpp
namespace Storage {
struct Time {
unsigned int length, clock_rate;
};
}
#endif /* Storage_h */

View File

@ -10,7 +10,7 @@
using namespace Storage; using namespace Storage;
void Tape::seek(Tape::Time seek_time) void Tape::seek(Time seek_time)
{ {
// TODO: as best we can // TODO: as best we can
} }

View File

@ -11,15 +11,23 @@
#include <memory> #include <memory>
#include "../../SignalProcessing/Stepper.hpp" #include "../../SignalProcessing/Stepper.hpp"
#include "../Storage.hpp"
namespace Storage { namespace Storage {
/*!
Models a tape as a sequence of pulses, each pulse being of arbitrary length and described
by their relationship with zero:
- high pulses exit from zero upward before returning to it;
- low pulses exit from zero downward before returning to it;
- zero pulses run along zero.
Subclasses should implement at least @c get_next_pulse and @c reset to provide a serial feeding
of pulses and the ability to return to the start of the feed. They may also implement @c seek if
a better implementation than a linear search from the @c reset time can be implemented.
*/
class Tape { class Tape {
public: public:
struct Time {
unsigned int length, clock_rate;
};
struct Pulse { struct Pulse {
enum { enum {
High, Low, Zero High, Low, Zero
@ -30,9 +38,16 @@ class Tape {
virtual Pulse get_next_pulse() = 0; virtual Pulse get_next_pulse() = 0;
virtual void reset() = 0; virtual void reset() = 0;
virtual void seek(Time seek_time); virtual void seek(Time seek_time); // TODO
}; };
/*!
Provides a helper for: (i) retaining a reference to a tape; and (ii) running the tape at a certain
input clock rate.
Will call @c process_input_pulse instantaneously upon reaching *the end* of a pulse. Therefore a subclass
can decode pulses into data within process_input_pulse, using the supplied pulse's @c length and @c type.
*/
class TapePlayer { class TapePlayer {
public: public:
TapePlayer(unsigned int input_clock_rate); TapePlayer(unsigned int input_clock_rate);