1 // license:BSD-3-Clause
2 // copyright-holders:Miodrag Milanovic, AJR
3 /***************************************************************************
4
5 PK-8020 driver by Miodrag Milanovic
6 based on work of Sergey Erokhin from pk8020.narod.ru
7
8 18/07/2008 Preliminary driver.
9
10 ****************************************************************************/
11
12
13 #include "emu.h"
14 #include "includes/pk8020.h"
15
16 #define DESCRIBE_DECPLM 1
17
18
keyboard_r(offs_t offset)19 uint8_t pk8020_state::keyboard_r(offs_t offset)
20 {
21 uint8_t result = 0xff;
22
23 if (BIT(offset, 8))
24 {
25 for (uint8_t line = 8; line < 16; line++)
26 if (BIT(offset, line - 8))
27 result &= m_io_port[line]->read();
28 }
29 else
30 {
31 for (uint8_t line = 0; line < 8; line++)
32 if (BIT(offset, line))
33 result &= m_io_port[line]->read();
34 }
35
36 return result ^ 0xff;
37 }
38
sysreg_w(offs_t offset,uint8_t data)39 void pk8020_state::sysreg_w(offs_t offset, uint8_t data)
40 {
41 if (!BIT(offset, 7))
42 {
43 m_bank_select = data & 0xfc;
44 logerror("%s: Bank select = %02X\n", machine().describe_context(), (data >> 2) & 0x1f);
45 }
46
47 if (!BIT(offset, 6))
48 color_w(data);
49 if (!BIT(offset, 2))
50 palette_w(data);
51 }
52
memory_r(offs_t offset)53 uint8_t pk8020_state::memory_r(offs_t offset)
54 {
55 uint8_t select = m_decplm->read(bitswap<13>((offset & 0xff00) | m_bank_select, 2, 5, 6, 4, 12, 3, 13, 8, 9, 11, 15, 10, 14) | 0x8000);
56 uint8_t result = 0xff;
57
58 if (!BIT(select, 2))
59 result &= m_region_maincpu->base()[offset & 0x1fff];
60 if (!BIT(select, 3))
61 result &= m_region_maincpu->base()[(offset & 0x1fff) | 0x2000];
62 if (!BIT(select, 0))
63 result &= m_region_maincpu->base()[(offset & 0x1fff) | 0x4000];
64 if (!BIT(select, 1))
65 result &= keyboard_r(offset);
66 if (!BIT(select, 4))
67 result &= m_devbank->read8(offset);
68
69 if ((select & 0xc0) == 0x00)
70 result &= m_ram->pointer()[offset];
71 else if ((select & 0xc0) == 0x40)
72 result &= gzu_r(offset & 0x3fff);
73 else if ((select & 0xc0) == 0x80)
74 result &= text_r(offset & 0x3ff);
75
76 return result;
77 }
78
memory_w(offs_t offset,uint8_t data)79 void pk8020_state::memory_w(offs_t offset, uint8_t data)
80 {
81 uint8_t select = m_decplm->read(bitswap<13>((offset & 0xff00) | m_bank_select, 2, 5, 6, 4, 12, 3, 13, 8, 9, 11, 15, 10, 14) | 0x2000);
82
83 if (!BIT(select, 5))
84 sysreg_w(offset, data);
85 if (!BIT(select, 4))
86 m_devbank->write8(offset, data);
87
88 if ((select & 0xc0) == 0x00)
89 m_ram->pointer()[offset] = data;
90 else if ((select & 0xc0) == 0x40)
91 gzu_w(offset & 0x3fff, data);
92 else if ((select & 0xc0) == 0x80)
93 text_w(offset & 0x3ff, data);
94 }
95
ppi_porta_r()96 uint8_t pk8020_state::ppi_porta_r()
97 {
98 return 0xf0 | (m_takt <<1) | (m_text_attr<<3) | ((m_cass->input() > +0.04) ? 1 : 0);
99 }
100
floppy_control_w(uint8_t data)101 void pk8020_state::floppy_control_w(uint8_t data)
102 {
103 floppy_image_device *floppy = nullptr;
104
105 // Turn all motors off
106 for (int n = 0; n < 4; n++)
107 if (m_floppy[n]->get_device())
108 m_floppy[n]->get_device()->mon_w(1);
109
110 for (int n = 0; n < 4; n++)
111 if (BIT(data, n))
112 floppy = m_floppy[n]->get_device();
113
114 m_fdc->set_floppy(floppy);
115
116 if (floppy)
117 {
118 floppy->mon_w(0);
119 floppy->ss_w(BIT(data, 4));
120 }
121
122 // todo: at least bit 5 and bit 7 is connected to something too...
123 }
124
125
ppi_2_portc_w(uint8_t data)126 void pk8020_state::ppi_2_portc_w(uint8_t data)
127 {
128 static const double levels[4] = { 0.0, 1.0, -1.0, 0.0 };
129 m_cass->output(levels[data & 3]);
130
131 m_sound_gate = BIT(data,3);
132 m_speaker->level_w(m_sound_gate ? m_sound_level : 0);
133
134 m_printer->write_select(!BIT(data, 4));
135 m_printer->write_strobe(!BIT(data, 5));
136 }
137
WRITE_LINE_MEMBER(pk8020_state::pit_out0)138 WRITE_LINE_MEMBER(pk8020_state::pit_out0)
139 {
140 m_sound_level = state;
141
142 m_speaker->level_w(m_sound_gate ? m_sound_level : 0);
143 }
144
145
plm_select_name(uint8_t data)146 const char *pk8020_state::plm_select_name(uint8_t data)
147 {
148 switch (data)
149 {
150 case 0xfb:
151 case 0xf7:
152 case 0xfe:
153 return "ROM";
154
155 case 0x3f:
156 return "RAM";
157
158 case 0xfd:
159 return "keyboard";
160
161 case 0xdf:
162 return "system reg";
163
164 case 0xef:
165 return "devices";
166
167 case 0xbf:
168 return "text video memory";
169
170 case 0x7f:
171 return "video RAM";
172
173 default:
174 return "multiple/unknown";
175 }
176 }
177
log_bank_select(uint8_t bank,offs_t start,offs_t end,uint8_t rdecplm,uint8_t wdecplm)178 void pk8020_state::log_bank_select(uint8_t bank, offs_t start, offs_t end, uint8_t rdecplm, uint8_t wdecplm)
179 {
180 if (rdecplm == wdecplm)
181 logerror("Bank select %02X, %04X-%04Xh: read/write %s (%02X)\n", bank, start, end, plm_select_name(rdecplm), rdecplm);
182 else
183 logerror("Bank select %02X, %04X-%04Xh: read %s (%02X), write %s (%02X)\n", bank, start, end, plm_select_name(rdecplm), rdecplm, plm_select_name(wdecplm), wdecplm);
184 }
185
machine_start()186 void pk8020_state::machine_start()
187 {
188 m_ios[0]->write_cts(0);
189 m_ios[1]->write_cts(0);
190 m_ios[1]->write_dsr(0);
191 m_takt = 0;
192
193 save_item(NAME(m_bank_select));
194 save_item(NAME(m_takt));
195 save_item(NAME(m_sound_gate));
196 save_item(NAME(m_sound_level));
197
198 if (DESCRIBE_DECPLM)
199 {
200 for (uint8_t bank = 0; bank < 0x20; bank++)
201 {
202 uint8_t rdecplm = 0;
203 uint8_t wdecplm = 0;
204 offs_t start = 0x0000;
205
206 for (offs_t offset = 0x0000; offset < 0x10000; offset += 0x100)
207 {
208 uint8_t rdecplm_test = m_decplm->read(bitswap<13>((offset & 0xff00) | (bank << 2), 2, 5, 6, 4, 12, 3, 13, 8, 9, 11, 15, 10, 14) | 0x8000);
209 uint8_t wdecplm_test = m_decplm->read(bitswap<13>((offset & 0xff00) | (bank << 2), 2, 5, 6, 4, 12, 3, 13, 8, 9, 11, 15, 10, 14) | 0x2000);
210
211 if (rdecplm != rdecplm_test || wdecplm != wdecplm_test)
212 {
213 if (offset != 0x0000)
214 log_bank_select(bank, start, offset - 1, rdecplm, wdecplm);
215 rdecplm = rdecplm_test;
216 wdecplm = wdecplm_test;
217 start = offset;
218 }
219 }
220 log_bank_select(bank, start, 0xffff, rdecplm, wdecplm);
221 }
222 }
223 }
224
machine_reset()225 void pk8020_state::machine_reset()
226 {
227 m_bank_select = 0;
228
229 m_sound_gate = 0;
230 m_sound_level = 0;
231 }
232
INTERRUPT_GEN_MEMBER(pk8020_state::pk8020_interrupt)233 INTERRUPT_GEN_MEMBER(pk8020_state::pk8020_interrupt)
234 {
235 m_takt ^= 1;
236 m_inr->ir4_w(m_takt);
237 }
238