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