openMSX
MSXPPI.cc
Go to the documentation of this file.
1 #include "MSXPPI.hh"
2 #include "LedStatus.hh"
3 #include "MSXCPUInterface.hh"
4 #include "MSXMotherBoard.hh"
5 #include "Reactor.hh"
6 #include "CassettePort.hh"
7 #include "RenShaTurbo.hh"
8 #include "serialize.hh"
9 
10 namespace openmsx {
11 
13  : MSXDevice(config)
14  , cassettePort(getMotherBoard().getCassettePort())
15  , renshaTurbo(getMotherBoard().getRenShaTurbo())
16  , i8255(*this, getCurrentTime(), getCliComm())
17  , click(config)
18  , keyboard(
19  config.getMotherBoard(),
20  config.getMotherBoard().getScheduler(),
21  config.getMotherBoard().getCommandController(),
22  config.getMotherBoard().getReactor().getEventDistributor(),
23  config.getMotherBoard().getMSXEventDistributor(),
24  config.getMotherBoard().getStateChangeDistributor(),
25  Keyboard::MATRIX_MSX, config)
26  , prevBits(15)
27  , selectedRow(0)
28 {
30 }
31 
33 {
34  powerDown(EmuTime::dummy());
35 }
36 
37 void MSXPPI::reset(EmuTime::param time)
38 {
39  i8255.reset(time);
40  click.reset(time);
41 }
42 
43 void MSXPPI::powerDown(EmuTime::param /*time*/)
44 {
46 }
47 
48 byte MSXPPI::readIO(word port, EmuTime::param time)
49 {
50  return i8255.read(port & 0x03, time);
51 }
52 
53 byte MSXPPI::peekIO(word port, EmuTime::param time) const
54 {
55  return i8255.peek(port & 0x03, time);
56 }
57 
58 void MSXPPI::writeIO(word port, byte value, EmuTime::param time)
59 {
60  i8255.write(port & 0x03, value, time);
61 }
62 
63 
64 // I8255Interface
65 
66 byte MSXPPI::readA(EmuTime::param time)
67 {
68  return peekA(time);
69 }
70 byte MSXPPI::peekA(EmuTime::param /*time*/) const
71 {
72  // port A is normally an output on MSX, reading from an output port
73  // is handled internally in the 8255
74  // TODO check this on a real MSX
75  // TODO returning 0 fixes the 'get_selected_slot' script right after
76  // reset (when PPI directions are not yet set). For now this
77  // solution is good enough.
78  return 0;
79 }
80 void MSXPPI::writeA(byte value, EmuTime::param /*time*/)
81 {
83 }
84 
85 byte MSXPPI::readB(EmuTime::param time)
86 {
87  return peekB(time);
88 }
89 byte MSXPPI::peekB(EmuTime::param time) const
90 {
91  auto& keyb = const_cast<Keyboard&>(keyboard);
92  if (selectedRow != 8) {
93  return keyb.getKeys()[selectedRow];
94  } else {
95  return keyb.getKeys()[8] | (renshaTurbo.getSignal(time) ? 1:0);
96  }
97 }
98 void MSXPPI::writeB(byte /*value*/, EmuTime::param /*time*/)
99 {
100  // probably nothing happens on a real MSX
101 }
102 
103 nibble MSXPPI::readC1(EmuTime::param time)
104 {
105  return peekC1(time);
106 }
107 nibble MSXPPI::peekC1(EmuTime::param /*time*/) const
108 {
109  return 15; // TODO check this
110 }
111 nibble MSXPPI::readC0(EmuTime::param time)
112 {
113  return peekC0(time);
114 }
115 nibble MSXPPI::peekC0(EmuTime::param /*time*/) const
116 {
117  return 15; // TODO check this
118 }
119 void MSXPPI::writeC1(nibble value, EmuTime::param time)
120 {
121  if ((prevBits ^ value) & 1) {
122  cassettePort.setMotor((value & 1) == 0, time); // 0=0n, 1=Off
123  }
124  if ((prevBits ^ value) & 2) {
125  cassettePort.cassetteOut((value & 2) != 0, time);
126  }
127  if ((prevBits ^ value) & 4) {
128  getLedStatus().setLed(LedStatus::CAPS, (value & 4) == 0);
129  }
130  if ((prevBits ^ value) & 8) {
131  click.setClick((value & 8) != 0, time);
132  }
133  prevBits = value;
134 }
135 void MSXPPI::writeC0(nibble value, EmuTime::param /*time*/)
136 {
137  selectedRow = value;
138 }
139 
140 
141 template<typename Archive>
142 void MSXPPI::serialize(Archive& ar, unsigned /*version*/)
143 {
144  ar.template serializeBase<MSXDevice>(*this);
145  ar.serialize("i8255", i8255);
146 
147  // merge prevBits and selectedRow into one byte
148  byte portC = (prevBits << 4) | (selectedRow << 0);
149  ar.serialize("portC", portC);
150  if (ar.isLoader()) {
151  selectedRow = (portC >> 0) & 0xF;
152  nibble bits = (portC >> 4) & 0xF;
153  writeC1(bits, getCurrentTime());
154  }
155  ar.serialize("keyboard", keyboard);
156 }
158 REGISTER_MSXDEVICE(MSXPPI, "PPI");
159 
160 } // namespace openmsx
const byte * getKeys() const
Returns a pointer to the current KeyBoard matrix.
Definition: Keyboard.cc:213
void serialize(Archive &ar, unsigned version)
Definition: MSXPPI.cc:142
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXPPI.cc:37
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
MSXPPI(const DeviceConfig &config)
Definition: MSXPPI.cc:12
void setPrimarySlots(byte value)
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
Definition: MSXPPI.cc:58
~MSXPPI() override
Definition: MSXPPI.cc:32
byte peek(byte port, EmuTime::param time) const
Definition: I8255.cc:60
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:129
void setClick(bool status, EmuTime::param time)
Definition: KeyClick.cc:16
LedStatus & getLedStatus() const
Definition: MSXDevice.cc:157
bool getSignal(EmuTime::param time)
Get the output signal in negative logic.
Definition: RenShaTurbo.cc:27
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX...
Definition: MSXDevice.hh:31
uint8_t nibble
4 bit integer
Definition: openmsx.hh:23
byte read(byte port, EmuTime::param time)
Definition: I8255.cc:43
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: MSXPPI.cc:53
void reset(EmuTime::param time)
Definition: I8255.cc:34
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: MSXPPI.cc:48
MSXCPUInterface & getCPUInterface() const
Definition: MSXDevice.cc:137
void powerDown(EmuTime::param time) override
This method is called when MSX is powered down.
Definition: MSXPPI.cc:43
void setLed(Led led, bool status)
Definition: LedStatus.cc:39
void reset(EmuTime::param time)
Definition: KeyClick.cc:11
void write(byte port, byte value, EmuTime::param time)
Definition: I8255.cc:77
virtual void cassetteOut(bool output, EmuTime::param time)=0
Writes one bit to the cassette port.
virtual void setMotor(bool status, EmuTime::param time)=0
Sets the cassette motor relay false = off true = on.