openMSX
VictorFDC.cc
Go to the documentation of this file.
1 #include "VictorFDC.hh"
2 #include "CacheLine.hh"
3 #include "DriveMultiplexer.hh"
4 #include "WD2793.hh"
5 #include "serialize.hh"
6 
7 // This implementation is documented in the HC-95 service manual:
8 //
9 // FDD interface:
10 // 7FF8 I/O FDC STATUS/COMMAND
11 // 7FF9 I/O FDC TRACK REGISTER
12 // 7FFA I/O FDC SECTOR REGISTER
13 // 7FFB I/O FDC DATA REGISTER
14 // 7FFC I/O bit 0 A DRIVE MOTOR ON/OFF "1" ON
15 // I/O bit 1 B DRIVE MOTOR ON/OFF "1" ON
16 // I/O bit 2 DRIVE SELECT "0" A DRIVE "1" B DRIVE
17 // O bit 3 SIDE SELECT "0" SIDE 0 "1" SIDE 1
18 // I SIDE SELECT "1" SIDE 0 "0" SIDE 1
19 // I/O bit 4 DRIVE ENABLE "0" ENABLE
20 // bit 5 unused
21 // I bit 6 FDC DATA REQUEST "1" REQUEST
22 // I bit 7 FDC INTERRUPT REQUEST "1" REQUEST
23 
24 namespace openmsx {
25 
26 constexpr int DRIVE_A_MOTOR = 0x01;
27 constexpr int DRIVE_B_MOTOR = 0x02;
28 constexpr int DRIVE_SELECT = 0x04;
29 constexpr int SIDE_SELECT = 0x08;
30 constexpr int DRIVE_DISABLE = 0x10; // renamed due to inverse logic
31 constexpr int DATA_REQUEST = 0x40;
32 constexpr int INTR_REQUEST = 0x80;
33 
34 
36  : WD2793BasedFDC(config)
37 {
39 }
40 
41 void VictorFDC::reset(EmuTime::param time)
42 {
44  // initialize in such way that drives are disabled
45  // (and motors off, etc.)
46  // TODO: test on real machine (this is an assumption)
47  writeMem(0x7FFC, DRIVE_DISABLE, time);
48 }
49 
50 byte VictorFDC::readMem(word address, EmuTime::param time)
51 {
52  switch (address) {
53  case 0x7FF8:
54  return controller.getStatusReg(time);
55  case 0x7FF9:
56  return controller.getTrackReg(time);
57  case 0x7FFA:
58  return controller.getSectorReg(time);
59  case 0x7FFB:
60  return controller.getDataReg(time);
61  case 0x7FFC: {
62  byte value = driveControls;
63  if (controller.getIRQ(time)) value |= INTR_REQUEST;
64  if (controller.getDTRQ(time)) value |= DATA_REQUEST;
65  value ^= SIDE_SELECT; // inverted
66  return value;
67  }
68  default:
69  return VictorFDC::peekMem(address, time);
70  }
71 }
72 
73 byte VictorFDC::peekMem(word address, EmuTime::param time) const
74 {
75  switch (address) {
76  case 0x7FF8:
77  return controller.peekStatusReg(time);
78  case 0x7FF9:
79  return controller.peekTrackReg(time);
80  case 0x7FFA:
81  return controller.peekSectorReg(time);
82  case 0x7FFB:
83  return controller.peekDataReg(time);
84  case 0x7FFC: {
85  byte value = driveControls;
86  if (controller.peekIRQ(time)) value |= INTR_REQUEST;
87  if (controller.peekDTRQ(time)) value |= DATA_REQUEST;
88  value ^= SIDE_SELECT; // inverted
89  return value;
90  }
91  default:
92  if ((0x4000 <= address) && (address < 0x8000)) {
93  // ROM only visible in 0x4000-0x7FFF
94  return MSXFDC::peekMem(address, time);
95  } else {
96  return 255;
97  }
98  }
99 }
100 
101 const byte* VictorFDC::getReadCacheLine(word start) const
102 {
103  if ((start & CacheLine::HIGH) == (0x7FF8 & CacheLine::HIGH)) {
104  // FDC at 0x7FF8-0x7FFC
105  return nullptr;
106  } else if ((0x4000 <= start) && (start < 0x8000)) {
107  // ROM at 0x4000-0x7FFF
108  return MSXFDC::getReadCacheLine(start);
109  } else {
110  return unmappedRead;
111  }
112 }
113 
114 void VictorFDC::writeMem(word address, byte value, EmuTime::param time)
115 {
116  switch (address) {
117  case 0x7FF8:
118  controller.setCommandReg(value, time);
119  break;
120  case 0x7FF9:
121  controller.setTrackReg(value, time);
122  break;
123  case 0x7FFA:
124  controller.setSectorReg(value, time);
125  break;
126  case 0x7FFB:
127  controller.setDataReg(value, time);
128  break;
129  case 0x7FFC:
131  = ((value & DRIVE_DISABLE) != 0)
133  : (((value & DRIVE_SELECT) != 0) ? DriveMultiplexer::DRIVE_B
135  multiplexer.selectDrive(drive, time);
136  multiplexer.setSide((value & SIDE_SELECT) != 0);
137  multiplexer.setMotor((drive == DriveMultiplexer::DRIVE_A) ? ((value & DRIVE_A_MOTOR) != 0) : ((value & DRIVE_B_MOTOR) != 0), time); // this is not 100% correct: the motors can be controlled independently via bit 0 and 1
138  // back up for reading:
139  driveControls = value & (DRIVE_A_MOTOR | DRIVE_B_MOTOR | DRIVE_SELECT | SIDE_SELECT | DRIVE_DISABLE);
140  break;
141  }
142 }
143 
144 byte* VictorFDC::getWriteCacheLine(word address) const
145 {
146  if ((address & CacheLine::HIGH) == (0x7FF8 & CacheLine::HIGH)) {
147  // FDC at 0x7FF8-0x7FFC
148  return nullptr;
149  } else {
150  return unmappedWrite;
151  }
152 }
153 
155 {
156  // OK, because this device doesn't call any 'fillDeviceXXXCache()'functions.
157  return true;
158 }
159 
160 
161 template<typename Archive>
162 void VictorFDC::serialize(Archive& ar, unsigned /*version*/)
163 {
164  ar.template serializeBase<WD2793BasedFDC>(*this);
165  ar.serialize("driveControls", driveControls);
166 }
169 
170 } // namespace openmsx
void setMotor(bool status, EmuTime::param time) override
Set motor on/off.
void selectDrive(DriveNum num, EmuTime::param time)
void setSide(bool side) override
Side select.
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:301
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:131
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:302
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: MSXFDC.cc:57
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: MSXFDC.cc:62
void reset(EmuTime::param time) override
This method is called on reset.
Definition: VictorFDC.cc:41
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition: VictorFDC.cc:144
bool allowUnaligned() const override
By default we don't allow unaligned <mem> specifications in the config file.
Definition: VictorFDC.cc:154
void serialize(Archive &ar, unsigned version)
Definition: VictorFDC.cc:162
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: VictorFDC.cc:50
void writeMem(word address, byte value, EmuTime::param time) override
Write a given byte to a given location at a certain time to this device.
Definition: VictorFDC.cc:114
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: VictorFDC.cc:101
VictorFDC(const DeviceConfig &config)
Definition: VictorFDC.cc:35
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: VictorFDC.cc:73
void reset(EmuTime::param time) override
This method is called on reset.
DriveMultiplexer multiplexer
bool peekIRQ(EmuTime::param time) const
Definition: WD2793.cc:110
byte peekStatusReg(EmuTime::param time) const
Definition: WD2793.cc:210
byte getTrackReg(EmuTime::param time) const
Definition: WD2793.cc:221
byte getDataReg(EmuTime::param time)
Definition: WD2793.cc:260
byte getSectorReg(EmuTime::param time) const
Definition: WD2793.cc:236
bool peekDTRQ(EmuTime::param time) const
Definition: WD2793.cc:95
bool getDTRQ(EmuTime::param time) const
Definition: WD2793.cc:90
byte getStatusReg(EmuTime::param time)
Definition: WD2793.cc:170
byte peekTrackReg(EmuTime::param time) const
Definition: WD2793.cc:226
void setTrackReg(byte value, EmuTime::param time)
Definition: WD2793.cc:216
void setDataReg(byte value, EmuTime::param time)
Definition: WD2793.cc:246
byte peekDataReg(EmuTime::param time) const
Definition: WD2793.cc:325
void setCommandReg(byte value, EmuTime::param time)
Definition: WD2793.cc:122
bool getIRQ(EmuTime::param time) const
Definition: WD2793.cc:105
void setSectorReg(byte value, EmuTime::param time)
Definition: WD2793.cc:231
byte peekSectorReg(EmuTime::param time) const
Definition: WD2793.cc:241
constexpr unsigned HIGH
Definition: CacheLine.hh:10
This file implemented 3 utility functions:
Definition: Autofire.cc:9
constexpr int DRIVE_SELECT
Definition: VictorFDC.cc:28
constexpr int DATA_REQUEST
Definition: VictorFDC.cc:31
constexpr int SIDE_SELECT
Definition: VictorFDC.cc:29
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
constexpr int INTR_REQUEST
Definition: VictorFDC.cc:32
constexpr int DRIVE_A_MOTOR
Definition: VictorFDC.cc:26
constexpr int DRIVE_B_MOTOR
Definition: VictorFDC.cc:27
constexpr int DRIVE_DISABLE
Definition: VictorFDC.cc:30
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:983