openMSX
WD2793.hh
Go to the documentation of this file.
1#ifndef WD2793_HH
2#define WD2793_HH
3
4#include "EmuTime.hh"
5#include "RawTrack.hh"
6#include "DynamicClock.hh"
7#include "Schedulable.hh"
8#include "CRC16.hh"
9#include "serialize_meta.hh"
10
11namespace openmsx {
12
13class Scheduler;
14class DiskDrive;
15class MSXCliComm;
16
17class WD2793 final : public Schedulable
18{
19public:
20 WD2793(Scheduler& scheduler, DiskDrive& drive, MSXCliComm& cliComm,
21 EmuTime::param time, bool isWD1770);
22
23 void reset(EmuTime::param time);
24
25 [[nodiscard]] uint8_t getStatusReg(EmuTime::param time);
26 [[nodiscard]] uint8_t getTrackReg (EmuTime::param time) const;
27 [[nodiscard]] uint8_t getSectorReg(EmuTime::param time) const;
28 [[nodiscard]] uint8_t getDataReg (EmuTime::param time);
29
30 [[nodiscard]] uint8_t peekStatusReg(EmuTime::param time) const;
31 [[nodiscard]] uint8_t peekTrackReg (EmuTime::param time) const;
32 [[nodiscard]] uint8_t peekSectorReg(EmuTime::param time) const;
33 [[nodiscard]] uint8_t peekDataReg (EmuTime::param time) const;
34
35 void setCommandReg(uint8_t value, EmuTime::param time);
36 void setTrackReg (uint8_t value, EmuTime::param time);
37 void setSectorReg (uint8_t value, EmuTime::param time);
38 void setDataReg (uint8_t value, EmuTime::param time);
39
40 [[nodiscard]] bool getIRQ (EmuTime::param time) const;
41 [[nodiscard]] bool getDTRQ(EmuTime::param time) const;
42
43 [[nodiscard]] bool peekIRQ (EmuTime::param time) const;
44 [[nodiscard]] bool peekDTRQ(EmuTime::param time) const;
45
46 template<typename Archive>
47 void serialize(Archive& ar, unsigned version);
48
49 // public for serialize
66
67private:
68 void executeUntil(EmuTime::param time) override;
69
70 void startType1Cmd(EmuTime::param time);
71
72 void seek(EmuTime::param time);
73 void step(EmuTime::param time);
74 void seekNext(EmuTime::param time);
75 void endType1Cmd(EmuTime::param time);
76
77 void startType2Cmd (EmuTime::param time);
78 void type2Loaded (EmuTime::param time);
79 void type2Search (EmuTime::param time);
80 void type2NotFound (EmuTime::param time);
81 void type2Rotated (EmuTime::param time);
82 void startReadSector (EmuTime::param time);
83 void startWriteSector(EmuTime::param time);
84 void checkStartWrite (EmuTime::param time);
85 void preWriteSector (EmuTime::param time);
86 void writeSectorData (EmuTime::param time);
87 void postWriteSector (EmuTime::param time);
88
89 void startType3Cmd (EmuTime::param time);
90 void type3Loaded (EmuTime::param time);
91 void type3Rotated (EmuTime::param time);
92 void readAddressCmd (EmuTime::param time);
93 void readTrackCmd (EmuTime::param time);
94 void startWriteTrack (EmuTime::param time);
95 void writeTrackData (EmuTime::param time);
96
97 void startType4Cmd(EmuTime::param time);
98
99 void endCmd(EmuTime::param time);
100
101 void setDrqRate(unsigned trackLength);
102 [[nodiscard]] bool isReady() const;
103
104 void schedule(FSMState state, EmuTime::param time);
105
106private:
107 DiskDrive& drive;
108 MSXCliComm& cliComm;
109
110 // DRQ is high iff current time is past this time.
111 // This clock ticks at the 'byte-rate' of the current track,
112 // typically '6250 bytes/rotation * 5 rotations/second'.
113 DynamicClock drqTime{EmuTime::infinity()};
114
115 // INTRQ is high iff current time is past this time.
116 EmuTime irqTime = EmuTime::infinity();
117
118 EmuTime pulse5 = EmuTime::infinity(); // time at which the 5th index pulse will be received
119
120 // HLD/HLT timing
121 // 1) now < hldTime (typically: hldTime == EmuTime::infinity)
122 // ==> HLD=false, WD2793 did not request head to be loaded
123 // 2) hldTime <= now < hldTime + LOAD
124 // ==> HLD=true, HLT=false, head loading is in progress
125 // 3) hldTime + LOAD <= now < hldTime + LOAD + IDLE
126 // ==> HLD=true, HLT=true, head is loaded
127 // 4) hldTime + LOAD + IDLE <= now
128 // ==> HLD=false, idle for 15 revolutions HLD made deactive again
129 // Note: is all MSX machines I've checked so far, WD2793 pins
130 // - HLD (pin 28) is unconnected
131 // - HLT (pin 40) is connected to +5V
132 // This means there is no head-load delay, or IOW as soon as the WD2793
133 // requests to load the disk head, the drive responds with "ok, done".
134 // So 'LOAD' is zero, and phase 2) doesn't exist. Therefor the current
135 // implementation mostly ignores 'LOAD'.
136 EmuTime hldTime = EmuTime::infinity(); // HLD=false
137
138 RawTrack::Sector sectorInfo;
139 int dataCurrent = 0; // which byte in track is next to be read/write
140 int dataAvailable = 0; // how many bytes left to read/write
141
142 CRC16 crc;
143
144 FSMState fsmState;
145 uint8_t statusReg;
146 uint8_t commandReg = 0;
147 uint8_t sectorReg;
148 uint8_t trackReg;
149 uint8_t dataReg;
150 uint8_t dataOutReg = 0;
151
152 bool directionIn;
153 bool immediateIRQ;
154 bool lastWasA1 = false;
155 bool dataRegWritten = false;
156 bool lastWasCRC = false;
157
158 const bool isWD1770;
159};
161
162} // namespace openmsx
163
164#endif
This (abstract) class defines the DiskDrive interface.
Definition DiskDrive.hh:13
Represents a clock with a variable frequency.
Every class that wants to get scheduled at some point must inherit from this class.
uint8_t peekDataReg(EmuTime::param time) const
Definition WD2793.cc:314
bool peekIRQ(EmuTime::param time) const
Definition WD2793.cc:99
@ FSM_POST_WRITE_SECTOR
Definition WD2793.hh:59
@ FSM_TYPE2_NOT_FOUND
Definition WD2793.hh:54
@ FSM_PRE_WRITE_SECTOR
Definition WD2793.hh:57
uint8_t getStatusReg(EmuTime::param time)
Definition WD2793.cc:159
void setTrackReg(uint8_t value, EmuTime::param time)
Definition WD2793.cc:205
void setSectorReg(uint8_t value, EmuTime::param time)
Definition WD2793.cc:220
uint8_t getTrackReg(EmuTime::param time) const
Definition WD2793.cc:210
uint8_t peekSectorReg(EmuTime::param time) const
Definition WD2793.cc:230
bool peekDTRQ(EmuTime::param time) const
Definition WD2793.cc:84
void setCommandReg(uint8_t value, EmuTime::param time)
Definition WD2793.cc:111
uint8_t peekTrackReg(EmuTime::param time) const
Definition WD2793.cc:215
bool getDTRQ(EmuTime::param time) const
Definition WD2793.cc:79
uint8_t peekStatusReg(EmuTime::param time) const
Definition WD2793.cc:199
void serialize(Archive &ar, unsigned version)
Definition WD2793.cc:1111
uint8_t getDataReg(EmuTime::param time)
Definition WD2793.cc:249
void setDataReg(uint8_t value, EmuTime::param time)
Definition WD2793.cc:235
bool getIRQ(EmuTime::param time) const
Definition WD2793.cc:94
uint8_t getSectorReg(EmuTime::param time) const
Definition WD2793.cc:225
void reset(EmuTime::param time)
Definition WD2793.cc:60
This file implemented 3 utility functions:
Definition Autofire.cc:9
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)