OXYGENHUB
◆ main openmsx / src / fdc / RealDrive.hh
4.0 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef REALDRIVE_HH
2
#define REALDRIVE_HH
3
4
#include "DiskChanger.hh"
5
#include "DiskDrive.hh"
6
7
#include "Clock.hh"
8
#include "MSXMotherBoard.hh"
9
#include "Schedulable.hh"
10
#include "ThrottleManager.hh"
11
#include "serialize_meta.hh"
12
13
#include "outer.hh"
14
15
#include <bitset>
16
#include <optional>
17
18
namespace openmsx {
19
20
/** This class implements a real drive, single or double sided.
21
 */
22
class RealDrive final : public DiskDrive, public MediaProvider
23
{
24
public:
25
	static constexpr unsigned MAX_DRIVES = 26; // a-z
26
	using DrivesInUse = std::bitset<MAX_DRIVES>;
27
	static std::shared_ptr<DrivesInUse> getDrivesInUse(MSXMotherBoard& motherBoard);
28
29
public:
30
	RealDrive(MSXMotherBoard& motherBoard, EmuDuration motorTimeout,
31
	          bool signalsNeedMotorOn, bool doubleSided, unsigned nominalTracks,
32
	          DiskDrive::TrackMode trackMode);
33
	~RealDrive() override;
34
35
	// DiskDrive interface
36
	[[nodiscard]] bool isDiskInserted() const override;
37
	[[nodiscard]] bool isWriteProtected() const override;
38
	[[nodiscard]] bool isDoubleSided() override;
39
	[[nodiscard]] bool isTrack00() const override;
40
	void setSide(bool side) override;
41
	[[nodiscard]] bool getSide() const override;
42
	void step(bool direction, EmuTime time) override;
43
	void setMotor(bool status, EmuTime time) override;
44
	[[nodiscard]] bool getMotor() const override;
45
	[[nodiscard]] bool indexPulse(EmuTime time) override;
46
	[[nodiscard]] EmuTime getTimeTillIndexPulse(EmuTime time, int count) override;
47
48
	[[nodiscard]] unsigned getTrackLength() override;
49
	void writeTrackByte(int idx, uint8_t val, bool addIdam) override;
50
	[[nodiscard]] uint8_t readTrackByte(int idx) override;
51
	EmuTime getNextSector(EmuTime time, RawTrack::Sector& sector) override;
52
	void flushTrack() override;
53
	bool diskChanged() override;
54
	[[nodiscard]] bool peekDiskChanged() const override;
55
	[[nodiscard]] bool isDummyDrive() const override;
56
57
	void applyWd2793ReadTrackQuirk() override;
58
	void invalidateWd2793ReadTrackQuirk() override;
59
60
	// MediaInfoProvider
61
	void getMediaInfo(TclObject& result) override;
62
	void setMedia(const TclObject& info, EmuTime time) override;
63
64
	template<typename Archive>
65
	void serialize(Archive& ar, unsigned version);
66
67
private:
68
	struct SyncLoadingTimeout final : Schedulable {
69
		friend class RealDrive;
70
		explicit SyncLoadingTimeout(Scheduler& s) : Schedulable(s) {}
71
		void executeUntil(EmuTime /*time*/) override {
72
			auto& drive = OUTER(RealDrive, syncLoadingTimeout);
73
			drive.execLoadingTimeout();
74
		}
75
	} syncLoadingTimeout;
76
77
	struct SyncMotorTimeout final : Schedulable {
78
		friend class RealDrive;
79
		explicit SyncMotorTimeout(Scheduler& s) : Schedulable(s) {}
80
		void executeUntil(EmuTime time) override {
81
			auto& drive = OUTER(RealDrive, syncMotorTimeout);
82
			drive.execMotorTimeout(time);
83
		}
84
	} syncMotorTimeout;
85
86
	void execLoadingTimeout();
87
	void execMotorTimeout(EmuTime time);
88
	[[nodiscard]] EmuTime getCurrentTime() const { return syncLoadingTimeout.getCurrentTime(); }
89
90
	void doSetMotor(bool status, EmuTime time);
91
	void setLoading(EmuTime time);
92
	[[nodiscard]] unsigned getCurrentAngle(EmuTime time) const;
93
94
	[[nodiscard]] unsigned getMaxTrack() const;
95
	[[nodiscard]] std::optional<unsigned> getDiskReadTrack() const;
96
	[[nodiscard]] std::optional<unsigned> getDiskWriteTrack() const;
97
	void getTrack();
98
	void invalidateTrack();
99
100
private:
101
	static constexpr unsigned TICKS_PER_ROTATION = 200000;
102
	static constexpr unsigned INDEX_DURATION = TICKS_PER_ROTATION / 50;
103
104
	MSXMotherBoard& motherBoard;
105
	LoadingIndicator loadingIndicator;
106
	const EmuDuration motorTimeout;
107
108
	using MotorClock = Clock<TICKS_PER_ROTATION * ROTATIONS_PER_SECOND>;
109
	MotorClock motorTimer;
110
	std::optional<DiskChanger> changer; // delayed initialization
111
	unsigned headPos = 0;
112
	unsigned side = 0;
113
	unsigned startAngle = 0;
114
	bool motorStatus = false;
115
	const bool doubleSizedDrive;
116
	const bool signalsNeedMotorOn;
117
	const DiskDrive::TrackMode trackMode;
118
119
	std::shared_ptr<DrivesInUse> drivesInUse;
120
121
	RawTrack track;
122
	bool trackValid = false;
123
	bool trackDirty = false;
124
};
125
SERIALIZE_CLASS_VERSION(RealDrive, 6);
126
127
} // namespace openmsx
128
129
#endif