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
24namespace openmsx {
25
26constexpr int DRIVE_A_MOTOR = 0x01;
27constexpr int DRIVE_B_MOTOR = 0x02;
28constexpr int DRIVE_SELECT = 0x04;
29constexpr int SIDE_SELECT = 0x08;
30constexpr int DRIVE_DISABLE = 0x10; // renamed due to inverse logic
31constexpr int DATA_REQUEST = 0x40;
32constexpr int INTR_REQUEST = 0x80;
33
34
36 : WD2793BasedFDC(config)
37{
39}
40
41void 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
50byte 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
73byte 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
101const 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
114void 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
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
161template<typename Archive>
162void 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:126
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:54
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:59
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:108
byte peekStatusReg(EmuTime::param time) const
Definition: WD2793.cc:208
byte getTrackReg(EmuTime::param time) const
Definition: WD2793.cc:219
byte getDataReg(EmuTime::param time)
Definition: WD2793.cc:258
byte getSectorReg(EmuTime::param time) const
Definition: WD2793.cc:234
bool peekDTRQ(EmuTime::param time) const
Definition: WD2793.cc:93
bool getDTRQ(EmuTime::param time) const
Definition: WD2793.cc:88
byte getStatusReg(EmuTime::param time)
Definition: WD2793.cc:168
byte peekTrackReg(EmuTime::param time) const
Definition: WD2793.cc:224
void setTrackReg(byte value, EmuTime::param time)
Definition: WD2793.cc:214
void setDataReg(byte value, EmuTime::param time)
Definition: WD2793.cc:244
byte peekDataReg(EmuTime::param time) const
Definition: WD2793.cc:323
void setCommandReg(byte value, EmuTime::param time)
Definition: WD2793.cc:120
bool getIRQ(EmuTime::param time) const
Definition: WD2793.cc:103
void setSectorReg(byte value, EmuTime::param time)
Definition: WD2793.cc:229
byte peekSectorReg(EmuTime::param time) const
Definition: WD2793.cc:239
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:1009