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:
parent
cf83258eaf
commit
9e3d6b762b
@ -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
9
Storage/Disk/Disk.cpp
Normal 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
66
Storage/Disk/Disk.hpp
Normal 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
20
Storage/Storage.hpp
Normal 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 */
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user