openMSX
SVIPPI.cc
Go to the documentation of this file.
1 #include "SVIPPI.hh"
2 #include "MSXMotherBoard.hh"
3 #include "Reactor.hh"
4 #include "CassettePort.hh"
5 #include "JoystickPort.hh"
6 #include "GlobalSettings.hh"
7 #include "serialize.hh"
8 
9 // Keyboard Matrix
10 //
11 // Column/ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
12 // Line | | | | | | | | |
13 // --------+-----+-----+-----+-----+-----+-----+-----+-----|
14 // 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
15 // 1 | 8 | 9 | : | ' | , | = | . | / |
16 // 2 | - | A | B | C | D | E | F | G |
17 // 3 | H | I | J | K | L | M | N | O |
18 // 4 | P | Q | R | S | T | U | V | W |
19 // 5 | X | Y | Z | [ | \ | ] | BS | UP |
20 // 6 |SHIFT|CTRL |LGRAP|RGRAP| ESC |STOP |ENTER|LEFT |
21 // 7 | F1 | F2 | F3 | F4 | F5 | CLS | INS |DOWN |
22 // 8 |SPACE| TAB | DEL |CAPS | SEL |PRINT| |RIGHT|
23 // 9* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
24 // 10* | 8 | 9 | + | - | * | / | . | , |
25 // ---------------------------------------------------------
26 // * Numerical keypad (SVI-328 only)
27 
28 // PPI Port A Input (98H)
29 // Bit Name Description
30 // 0 TA Paddle or tablet 1, /SENSE
31 // 1 TB Paddle or tablet 1, EOC
32 // 2 TC Paddle or tablet 2, /SENSE
33 // 3 TD Paddle or tablet 2, EOC
34 // 4 /TRIGGER1 Joystick 1, Trigger
35 // 5 /TRIGGER2 Joystick 2, Trigger
36 // 6 /READY Cassette, Ready
37 // 7 CASR Cassette, Read data
38 //
39 // PPI Port B Input (99H)
40 // Bit Name Description
41 // 0 IN0 Keyboard, Column status of selected line
42 // 1 IN1 Keyboard, Column status of selected line
43 // 2 IN2 Keyboard, Column status of selected line
44 // 3 IN3 Keyboard, Column status of selected line
45 // 4 IN4 Keyboard, Column status of selected line
46 // 5 IN5 Keyboard, Column status of selected line
47 // 6 IN6 Keyboard, Column status of selected line
48 // 7 IN7 Keyboard, Column status of selected line
49 //
50 // PPI Port C Output (96H)
51 // Bit Name Description
52 // 0 KB0 Keyboard, Line select 0
53 // 1 KB1 Keyboard, Line select 1
54 // 2 KB2 Keyboard, Line select 2
55 // 3 KB3 Keyboard, Line select 3
56 // 4 CASON Cassette, Motor relay control (0=on, 1=off)
57 // 5 CASW Cassette, Write data
58 // 6 CASAUD Cassette, Audio control (1=enable other channel in, 0=disable channel)
59 // 7 SOUND Keyboard, Click sound bit (pulse)
60 //
61 // PPI Mode control, Output (97H)
62 //
63 // PPI Port C, Input (9AH)
64 
65 namespace openmsx {
66 
67 // MSXDevice
68 
70  : MSXDevice(config)
71  , cassettePort(getMotherBoard().getCassettePort())
72  , i8255(*this, getCurrentTime(), config.getGlobalSettings().getInvalidPpiModeSetting())
73  , click(config)
74  , keyboard(
75  config.getMotherBoard(),
76  config.getMotherBoard().getScheduler(),
77  config.getMotherBoard().getCommandController(),
78  config.getMotherBoard().getReactor().getEventDistributor(),
79  config.getMotherBoard().getMSXEventDistributor(),
80  config.getMotherBoard().getStateChangeDistributor(),
81  Keyboard::MATRIX_SVI, config)
82  , prevBits(15)
83  , selectedRow(0)
84 {
85  ports[0] = &getMotherBoard().getJoystickPort(0);
86  ports[1] = &getMotherBoard().getJoystickPort(1);
87 
88  auto time = getCurrentTime();
89  ports[0]->write(0, time); // TODO correct? Bit2 must be 0 otherwise
90  ports[1]->write(0, time); // e.g. KeyJoystick doesn't work
91 
92  reset(time);
93 }
94 
95 void SVIPPI::reset(EmuTime::param time)
96 {
97  i8255.reset(time);
98  click.reset(time);
99 }
100 
101 byte SVIPPI::readIO(word port, EmuTime::param time)
102 {
103  return i8255.read(port & 0x03, time);
104 }
105 
106 byte SVIPPI::peekIO(word port, EmuTime::param time) const
107 {
108  return i8255.peek(port & 0x03, time);
109 }
110 
111 void SVIPPI::writeIO(word port, byte value, EmuTime::param time)
112 {
113  i8255.write(port & 0x03, value, time);
114 }
115 
116 
117 // I8255Interface
118 
119 byte SVIPPI::readA(EmuTime::param time)
120 {
121  byte triggers = ((ports[0]->read(time) & 0x10) ? 0x10 : 0) |
122  ((ports[1]->read(time) & 0x10) ? 0x20 : 0);
123 
124  //byte cassetteReady = cassettePort.Ready() ? 0 : 0x40;
125  byte cassetteReady = 0; // ready
126 
127  byte cassetteInput = cassettePort.cassetteIn(time) ? 0x80 : 0x00;
128 
129  return triggers | cassetteReady | cassetteInput;
130 }
131 byte SVIPPI::peekA(EmuTime::param /*time*/) const
132 {
133  return 0; // TODO
134 }
135 void SVIPPI::writeA(byte /*value*/, EmuTime::param /*time*/)
136 {
137 }
138 
139 byte SVIPPI::readB(EmuTime::param time)
140 {
141  return peekB(time);
142 }
143 byte SVIPPI::peekB(EmuTime::param /*time*/) const
144 {
145  auto& keyb = const_cast<Keyboard&>(keyboard);
146  return keyb.getKeys()[selectedRow];
147 }
148 void SVIPPI::writeB(byte /*value*/, EmuTime::param /*time*/)
149 {
150 }
151 
152 nibble SVIPPI::readC1(EmuTime::param time)
153 {
154  return peekC1(time);
155 }
156 nibble SVIPPI::peekC1(EmuTime::param /*time*/) const
157 {
158  return 15; // TODO check this
159 }
160 nibble SVIPPI::readC0(EmuTime::param time)
161 {
162  return peekC0(time);
163 }
164 nibble SVIPPI::peekC0(EmuTime::param /*time*/) const
165 {
166  return selectedRow;
167 }
168 void SVIPPI::writeC1(nibble value, EmuTime::param time)
169 {
170  if ((prevBits ^ value) & 1) {
171  cassettePort.setMotor((value & 1) == 0, time); // 0=0n, 1=Off
172  }
173  if ((prevBits ^ value) & 2) {
174  cassettePort.cassetteOut((value & 2) != 0, time);
175  }
176  //if ((prevBits ^ value) & 4) {
177  // cassetteDevice.Mute(); // CASAUD, mute case speaker (1=enable, 0=disable)
178  //}
179  if ((prevBits ^ value) & 8) {
180  click.setClick((value & 8) != 0, time);
181  }
182  prevBits = value;
183 }
184 void SVIPPI::writeC0(nibble value, EmuTime::param /*time*/)
185 {
186  selectedRow = value;
187 }
188 
189 template<typename Archive>
190 void SVIPPI::serialize(Archive& ar, unsigned /*version*/)
191 {
192  ar.template serializeBase<MSXDevice>(*this);
193  ar.serialize("i8255", i8255);
194 
195  // merge prevBits and selectedRow into one byte
196  byte portC = (prevBits << 4) | (selectedRow << 0);
197  ar.serialize("portC", portC);
198  if (ar.isLoader()) {
199  selectedRow = (portC >> 0) & 0xF;
200  nibble bits = (portC >> 4) & 0xF;
201  writeC1(bits, getCurrentTime());
202  }
203  ar.serialize("keyboard", keyboard);
204 }
206 REGISTER_MSXDEVICE(SVIPPI, "SVI-328 PPI");
207 
208 } // namespace openmsx
openmsx::MSXDevice
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:32
openmsx::SVIPPI::serialize
void serialize(Archive &ar, unsigned version)
Definition: SVIPPI.cc:190
openmsx::CassettePortInterface::cassetteOut
virtual void cassetteOut(bool output, EmuTime::param time)=0
Writes one bit to the cassette port.
serialize.hh
openmsx::SVIPPI::reset
void reset(EmuTime::param time) override
This method is called on reset.
Definition: SVIPPI.cc:95
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::MSXMotherBoard::getJoystickPort
JoystickPortIf & getJoystickPort(unsigned port)
Definition: MSXMotherBoard.cc:441
JoystickPort.hh
openmsx::CassettePortInterface::cassetteIn
virtual bool cassetteIn(EmuTime::param time)=0
Reads one bit from the cassette port.
openmsx::KeyClick::setClick
void setClick(bool status, EmuTime::param time)
Definition: KeyClick.cc:16
openmsx::REGISTER_MSXDEVICE
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
SVIPPI.hh
Reactor.hh
openmsx::I8255::reset
void reset(EmuTime::param time)
Definition: I8255.cc:33
openmsx::SVIPPI::peekIO
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: SVIPPI.cc:106
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:982
openmsx::MSXDevice::getMotherBoard
MSXMotherBoard & getMotherBoard() const
Get the mother board this device belongs to.
Definition: MSXDevice.cc:75
openmsx::Keyboard
Keyboard
Definition: Keyboard.cc:1382
openmsx::Keyboard
Definition: Keyboard.hh:37
openmsx::I8255::read
byte read(byte port, EmuTime::param time)
Definition: I8255.cc:42
openmsx::SVIPPI::SVIPPI
SVIPPI(const DeviceConfig &config)
Definition: SVIPPI.cc:69
GlobalSettings.hh
openmsx::SVIPPI
Definition: SVIPPI.hh:18
openmsx::word
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
openmsx::SVIPPI::readIO
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: SVIPPI.cc:101
openmsx::JoystickPortIf::write
virtual void write(byte value, EmuTime::param time)=0
openmsx::JoystickPortIf::read
virtual byte read(EmuTime::param time)=0
openmsx::CassettePortInterface::setMotor
virtual void setMotor(bool status, EmuTime::param time)=0
Sets the cassette motor relay false = off true = on.
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
MSXMotherBoard.hh
openmsx::SVIPPI::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: SVIPPI.cc:111