OXYGENHUB
◆ main openmsx / src / fdc / TC8566AF.hh
3.5 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef TC8566AF_HH
2
#define TC8566AF_HH
3
4
#include "DynamicClock.hh"
5
#include "EmuTime.hh"
6
#include "Schedulable.hh"
7
#include "serialize_meta.hh"
8
9
#include "CRC16.hh"
10
11
#include <array>
12
#include <cstdint>
13
#include <span>
14
15
namespace openmsx {
16
17
class Scheduler;
18
class DiskDrive;
19
class MSXCliComm;
20
21
class TC8566AF final : public Schedulable
22
{
23
public:
24
	TC8566AF(Scheduler& scheduler, std::span<std::unique_ptr<DiskDrive>, 4>, MSXCliComm& cliComm,
25
	         EmuTime time);
26
27
	void reset(EmuTime time);
28
	[[nodiscard]] uint8_t peekDataPort(EmuTime time) const;
29
	uint8_t readDataPort(EmuTime time);
30
	[[nodiscard]] uint8_t peekStatus() const;
31
	uint8_t readStatus(EmuTime time);
32
	void writeControlReg0(uint8_t value, EmuTime time);
33
	void writeControlReg1(uint8_t value, EmuTime time);
34
	void writeDataPort(uint8_t value, EmuTime time);
35
	bool diskChanged(unsigned driveNum);
36
	[[nodiscard]] bool peekDiskChanged(unsigned driveNum) const;
37
38
	template<typename Archive>
39
	void serialize(Archive& ar, unsigned version);
40
41
	// public for serialization
42
	enum class Command : uint8_t {
43
		UNKNOWN,
44
		READ_DATA,
45
		WRITE_DATA,
46
		WRITE_DELETED_DATA,
47
		READ_DELETED_DATA,
48
		READ_DIAGNOSTIC,
49
		READ_ID,
50
		FORMAT,
51
		SCAN_EQUAL,
52
		SCAN_LOW_OR_EQUAL,
53
		SCAN_HIGH_OR_EQUAL,
54
		SEEK,
55
		RECALIBRATE,
56
		SENSE_INTERRUPT_STATUS,
57
		SPECIFY,
58
		SENSE_DEVICE_STATUS,
59
	};
60
	enum class Phase : uint8_t {
61
		IDLE,
62
		COMMAND,
63
		DATA_TRANSFER,
64
		RESULT,
65
	};
66
	enum class Seek : uint8_t {
67
		IDLE,
68
		SEEK,
69
		RECALIBRATE
70
	};
71
72
private:
73
	// Schedulable
74
	void executeUntil(EmuTime time) override;
75
76
	[[nodiscard]] uint8_t executionPhasePeek(EmuTime time) const;
77
	uint8_t executionPhaseRead(EmuTime time);
78
	[[nodiscard]] uint8_t resultsPhasePeek() const;
79
	uint8_t resultsPhaseRead(EmuTime time);
80
	void idlePhaseWrite(uint8_t value, EmuTime time);
81
	void commandPhase1(uint8_t value);
82
	void commandPhaseWrite(uint8_t value, EmuTime time);
83
	void doSeek(int n);
84
	void executionPhaseWrite(uint8_t value, EmuTime time);
85
	void resultPhase(bool readId = false);
86
	void endCommand(EmuTime time);
87
88
	[[nodiscard]] bool isHeadLoaded(EmuTime time) const;
89
	[[nodiscard]] EmuDuration getHeadLoadDelay() const;
90
	[[nodiscard]] EmuDuration getHeadUnloadDelay() const;
91
	[[nodiscard]] EmuDuration getSeekDelay() const;
92
93
	[[nodiscard]] EmuTime locateSector(EmuTime time, bool readId);
94
	void startReadWriteSector(EmuTime time);
95
	void writeSector();
96
	void initTrackHeader(EmuTime time);
97
	void formatSector();
98
	void setDrqRate(unsigned trackLength);
99
100
private:
101
	MSXCliComm& cliComm;
102
	std::array<DiskDrive*, 4> drive;
103
	DynamicClock delayTime{EmuTime::zero()};
104
105
	// Before this time head is loaded, after this time it's unloaded. Set
106
	// to zero/infinity to force a (un)loaded head.
107
	EmuTime headUnloadTime = EmuTime::zero(); // head not loaded
108
109
	Command command;
110
	Phase phase;
111
	int phaseStep;
112
113
	//bool interrupt;
114
115
	unsigned dataAvailable = 0; // avoid UMR (on savestate)
116
	int dataCurrent = 0;
117
	CRC16 crc;
118
119
	uint8_t driveSelect;
120
	uint8_t mainStatus;
121
	uint8_t status0;
122
	uint8_t status1;
123
	uint8_t status2;
124
	uint8_t status3;
125
	uint8_t commandCode;
126
127
	uint8_t cylinderNumber;
128
	uint8_t headNumber;
129
	uint8_t sectorNumber;
130
	uint8_t number;
131
	uint8_t endOfTrack;
132
	uint8_t sectorsPerCylinder;
133
	uint8_t fillerByte;
134
	uint8_t gapLength;
135
	std::array<uint8_t, 2> specifyData; // filled in by SPECIFY command
136
137
	struct SeekInfo {
138
		EmuTime time = EmuTime::zero();
139
		uint8_t currentTrack = 0;
140
		uint8_t seekValue = 0;
141
		Seek state = Seek::IDLE;
142
143
		template<typename Archive>
144
		void serialize(Archive& ar, unsigned version);
145
	};
146
	std::array<SeekInfo, 4> seekInfo;
147
};
148
SERIALIZE_CLASS_VERSION(TC8566AF, 7);
149
150
} // namespace openmsx
151
152
#endif