1 // license:BSD-3-Clause
2 // copyright-holders:Carl
3
4 /*********************************************************************************************
5 The keyboard has a sticker that proclaims it was made by Fujitsu Limited.
6
7 [ASC] [ESC] [F1 ] [F2 ] [F3 ] [F4 ] [F5 ] [F6 ] [F7 ] [F8 ] [F9 ] [F10] [F11] [F11] [PRN]
8 [mu°] [1 !] [2 "] [3 §] [4 $] [5 %] [6 &] [7 /] [8 (] [9 )] [0 =] [ß ?] [´ `] [BKS] [ C ] [ 7 ] [ 8 ] [ 9 ] [<- ] [ ->]
9 [ TAB ] [ Q ] [ W ] [ E ] [ R ] [ T ] [ Z ] [ U ] [ I ] [ O ] [ P ] [ Ü ] [+ *] [ DEL ] [ 4 ] [ 5 ] [ 5 ] [ - ] [HOM]
10 [SHIFTLOCK] [ A ] [ S ] [ D ] [ F ] [ G ] [ H ] [ J ] [ K ] [ L ] [ Ö ] [ Ä ] [# '] [RET] [ 1 ] [ 2 ] [ 3 ] [RET] [UP ]
11 [SHIFT] [2 3] [ Y ] [ X ] [ C ] [ V ] [ B ] [ N ] [ M ] [, ;] [. :] [- _] [ Ü ] [URN] [ 0 ] [ . ] [URN] [DWN]
12 [ CTRL ] [ SPACE ]
13
14 * The ASC key top left has a red LED, "Depressing the ASCII key, [...], switches off the LED indicator. This key acts as a
15 toggle between the ASCII character set, and your country's standard (NATIONAL) character set. You would use this feature if
16 you wanted to work with another character set, such as French or Spanish."
17 * the mu° has the Greek lowercase mu and the degree characters
18 * PRN is PRINT
19 * BKS is the full word BACKSPACE
20 * the C to the right of BKS has a red keycap, it deletes the complete line
21 * the five direction keys are all marked with arrows, HOME being diagonally to the top left
22 * SHIFTLOCK also has an LED indicator, and is released by pressing one of the SHIFT keys
23
24 **********************************************************************************************/
25
26 #include "emu.h"
27 #include "cpu/i86/i86.h"
28 #include "cpu/mcs48/mcs48.h"
29 #include "imagedev/floppy.h"
30 #include "machine/pic8259.h"
31 #include "machine/pit8253.h"
32 #include "machine/i8255.h"
33 #include "machine/i8251.h"
34 #include "machine/i8257.h"
35 #include "machine/upd765.h"
36 #include "video/mc6845.h"
37 #include "bus/rs232/rs232.h"
38 #include "bus/rs232/keyboard.h"
39 #include "emupal.h"
40 #include "screen.h"
41
42 class peoplepc_state : public driver_device
43 {
44 public:
peoplepc_state(const machine_config & mconfig,device_type type,const char * tag)45 peoplepc_state(const machine_config &mconfig, device_type type, const char *tag) :
46 driver_device(mconfig, type, tag),
47 m_maincpu(*this, "maincpu"),
48 m_palette(*this, "palette"),
49 m_pic_1(*this, "pic8259_1"),
50 m_8251key(*this, "i8251_0"),
51 m_8251ser(*this, "i8251_1"),
52 m_fdc(*this, "upd765"),
53 m_flop0(*this, "upd765:0"),
54 m_flop1(*this, "upd765:1"),
55 m_dmac(*this, "i8257"),
56 m_crtc(*this, "h46505"),
57 m_gfxdecode(*this, "gfxdecode"),
58 m_gvram(*this, "gvram"),
59 m_cvram(*this, "cvram"),
60 m_charram(4*1024)
61 { }
62
63 void olypeopl(machine_config &config);
64
65 private:
66 required_device<cpu_device> m_maincpu;
67 required_device<palette_device> m_palette;
68 required_device<pic8259_device> m_pic_1;
69 required_device<i8251_device> m_8251key;
70 required_device<i8251_device> m_8251ser;
71 required_device<upd765a_device> m_fdc;
72 required_device<floppy_connector> m_flop0;
73 required_device<floppy_connector> m_flop1;
74 required_device<i8257_device> m_dmac;
75 required_device<hd6845s_device> m_crtc;
76 required_device<gfxdecode_device> m_gfxdecode;
77 required_shared_ptr<uint16_t> m_gvram;
78 required_shared_ptr<uint16_t> m_cvram;
79 std::vector<uint8_t> m_charram;
80
81 MC6845_UPDATE_ROW(update_row);
82 uint8_t get_slave_ack(offs_t offset);
83 void charram_w(offs_t offset, uint16_t data);
84 void dmapg_w(uint8_t data);
85 void p7c_w(uint8_t data);
86 DECLARE_WRITE_LINE_MEMBER(tc_w);
87 DECLARE_WRITE_LINE_MEMBER(hrq_w);
88 uint8_t memory_read_byte(offs_t offset);
89 void memory_write_byte(offs_t offset, uint8_t data);
90 DECLARE_FLOPPY_FORMATS( floppy_formats );
91 image_init_result floppy_load(floppy_image_device *dev);
92 void floppy_unload(floppy_image_device *dev);
93
94 uint8_t m_dma0pg, m_p7c;
95 void peoplepc_io(address_map &map);
96 void peoplepc_map(address_map &map);
97
98 virtual void machine_start() override;
99 virtual void machine_reset() override;
100 };
101
102 static const gfx_layout peoplepc_charlayout =
103 {
104 8, 19, /* 8 x 19 characters */
105 128, /* 128 characters */
106 1, /* 1 bits per pixel */
107 { 0 }, /* no bitplanes */
108 /* x offsets */
109 { 7, 6, 5, 4, 3, 2, 1, 0},
110 /* y offsets */
111 { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8, 16*8, 17*8, 18*8 },
112 8*32
113 };
114
MC6845_UPDATE_ROW(peoplepc_state::update_row)115 MC6845_UPDATE_ROW(peoplepc_state::update_row)
116 {
117 rgb_t const *const palette = m_palette->palette()->entry_list_raw();
118
119 for(int i = 0; i < x_count; i++)
120 {
121 if(BIT(m_p7c, 1))
122 {
123 uint16_t data = m_gvram[((((ma / 40) * 16) + ra) * 64) + i];
124
125 for(int j = 15; j >= 0; j--)
126 bitmap.pix(y, (i * 16) + j) = palette[BIT(data, j)];
127 }
128 else
129 {
130 uint16_t data = m_cvram[(ma + i) & 0x3fff];
131 uint8_t chr = m_charram[(data & 0x7f) * 32 + ra];
132 if(data & 0x1000)
133 chr ^= 0xff;
134 if(((data & 0x800) && (ra > 14)) || (i == cursor_x))
135 chr = 0xff;
136 for(int j = 0; j < 8; j++)
137 bitmap.pix(y, (i * 8) + j) = palette[BIT(chr, j)];
138 }
139 }
140 }
141
get_slave_ack(offs_t offset)142 uint8_t peoplepc_state::get_slave_ack(offs_t offset)
143 {
144 if (offset == 7)
145 return m_pic_1->acknowledge();
146
147 return 0x00;
148 }
149
charram_w(offs_t offset,uint16_t data)150 void peoplepc_state::charram_w(offs_t offset, uint16_t data)
151 {
152 m_charram[offset] = data;
153 m_gfxdecode->gfx(0)->mark_dirty(offset/16);
154 }
155
dmapg_w(uint8_t data)156 void peoplepc_state::dmapg_w(uint8_t data)
157 {
158 m_dma0pg = data;
159 }
160
p7c_w(uint8_t data)161 void peoplepc_state::p7c_w(uint8_t data)
162 {
163 m_p7c = data;
164 m_crtc->set_hpixels_per_column(BIT(data, 1) ? 16 : 8);
165 }
166
WRITE_LINE_MEMBER(peoplepc_state::tc_w)167 WRITE_LINE_MEMBER(peoplepc_state::tc_w)
168 {
169 m_fdc->tc_w(state);
170 }
171
WRITE_LINE_MEMBER(peoplepc_state::hrq_w)172 WRITE_LINE_MEMBER(peoplepc_state::hrq_w)
173 {
174 m_maincpu->set_input_line(INPUT_LINE_HALT, state);
175 m_dmac->hlda_w(state);
176 }
177
memory_read_byte(offs_t offset)178 uint8_t peoplepc_state::memory_read_byte(offs_t offset)
179 {
180 address_space& prog_space = m_maincpu->space(AS_PROGRAM);
181 return prog_space.read_byte(offset | (m_dma0pg << 16));
182 }
183
memory_write_byte(offs_t offset,uint8_t data)184 void peoplepc_state::memory_write_byte(offs_t offset, uint8_t data)
185 {
186 address_space& prog_space = m_maincpu->space(AS_PROGRAM);
187 prog_space.write_byte(offset | (m_dma0pg << 16), data);
188 }
189
floppy_load(floppy_image_device * dev)190 image_init_result peoplepc_state::floppy_load(floppy_image_device *dev)
191 {
192 dev->mon_w(0);
193 return image_init_result::PASS;
194 }
195
floppy_unload(floppy_image_device * dev)196 void peoplepc_state::floppy_unload(floppy_image_device *dev)
197 {
198 dev->mon_w(1);
199 }
200
machine_reset()201 void peoplepc_state::machine_reset()
202 {
203 m_flop0->get_device()->mon_w(!m_flop0->get_device()->exists());
204 m_flop1->get_device()->mon_w(!m_flop1->get_device()->exists());
205 }
206
machine_start()207 void peoplepc_state::machine_start()
208 {
209 m_gfxdecode->set_gfx(0, std::make_unique<gfx_element>(m_palette, peoplepc_charlayout, &m_charram[0], 0, 1, 0));
210 m_dma0pg = 0;
211
212 // FIXME: cheat as there no docs about how or obvious ports that set to control the motor
213 m_flop0->get_device()->setup_load_cb(floppy_image_device::load_cb(&peoplepc_state::floppy_load, this));
214 m_flop0->get_device()->setup_unload_cb(floppy_image_device::unload_cb(&peoplepc_state::floppy_unload, this));
215 m_flop1->get_device()->setup_load_cb(floppy_image_device::load_cb(&peoplepc_state::floppy_load, this));
216 m_flop1->get_device()->setup_unload_cb(floppy_image_device::unload_cb(&peoplepc_state::floppy_unload, this));
217 }
218
peoplepc_map(address_map & map)219 void peoplepc_state::peoplepc_map(address_map &map)
220 {
221 map.unmap_value_high();
222 map(0x00000, 0x7ffff).ram();
223 map(0xc0000, 0xdffff).ram().share("gvram");
224 map(0xe0000, 0xe3fff).ram().share("cvram");
225 map(0xe4000, 0xe5fff).w(FUNC(peoplepc_state::charram_w));
226 map(0xfe000, 0xfffff).rom().region("maincpu", 0);
227 }
228
peoplepc_io(address_map & map)229 void peoplepc_state::peoplepc_io(address_map &map)
230 {
231 map.unmap_value_high();
232 map(0x0014, 0x0017).rw(m_pic_1, FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff);
233 map(0x0018, 0x001b).rw("pic8259_0", FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff);
234 map(0x0020, 0x0031).rw(m_dmac, FUNC(i8257_device::read), FUNC(i8257_device::write)).umask16(0x00ff);
235 map(0x0040, 0x0047).rw("ppi8255", FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff);
236 map(0x0048, 0x004f).rw("pit8253", FUNC(pit8253_device::read), FUNC(pit8253_device::write)).umask16(0x00ff);
237 map(0x0054, 0x0057).rw(m_8251key, FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff);
238 map(0x005c, 0x005f).rw(m_8251ser, FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff);
239 map(0x0064, 0x0067).m(m_fdc, FUNC(upd765a_device::map)).umask16(0x00ff);
240 map(0x006c, 0x006c).w("h46505", FUNC(mc6845_device::address_w));
241 map(0x006e, 0x006e).rw("h46505", FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
242 map(0x0070, 0x0070).w(FUNC(peoplepc_state::dmapg_w));
243 map(0x007c, 0x007c).w(FUNC(peoplepc_state::p7c_w));
244 }
245
peoplepc_floppies(device_slot_interface & device)246 static void peoplepc_floppies(device_slot_interface &device)
247 {
248 device.option_add("525qd", FLOPPY_525_QD);
249 }
250
FLOPPY_FORMATS_MEMBER(peoplepc_state::floppy_formats)251 FLOPPY_FORMATS_MEMBER( peoplepc_state::floppy_formats )
252 FLOPPY_IMD_FORMAT
253 FLOPPY_FORMATS_END
254
255 void peoplepc_keyboard_devices(device_slot_interface &device)
256 {
257 device.option_add("keyboard", SERIAL_KEYBOARD);
258 }
259
260 static DEVICE_INPUT_DEFAULTS_START(keyboard)
261 DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_1200 )
262 DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
263 DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
264 DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_EVEN )
265 DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
266 DEVICE_INPUT_DEFAULTS_END
267
olypeopl(machine_config & config)268 void peoplepc_state::olypeopl(machine_config &config)
269 {
270 /* basic machine hardware */
271 I8086(config, m_maincpu, XTAL(14'745'600)/3);
272 m_maincpu->set_addrmap(AS_PROGRAM, &peoplepc_state::peoplepc_map);
273 m_maincpu->set_addrmap(AS_IO, &peoplepc_state::peoplepc_io);
274 m_maincpu->set_irq_acknowledge_callback("pic8259_0", FUNC(pic8259_device::inta_cb));
275
276 pit8253_device &pit8253(PIT8253(config, "pit8253"));
277 pit8253.set_clk<0>(XTAL(14'745'600)/6);
278 pit8253.out_handler<0>().set(m_8251key, FUNC(i8251_device::write_txc));
279 pit8253.out_handler<0>().append(m_8251key, FUNC(i8251_device::write_rxc));
280 pit8253.out_handler<0>().append("pit8253", FUNC(pit8253_device::write_clk2));
281 pit8253.set_clk<1>(XTAL(14'745'600)/6);
282 pit8253.out_handler<1>().set(m_8251ser, FUNC(i8251_device::write_txc));
283 pit8253.out_handler<1>().append(m_8251ser, FUNC(i8251_device::write_rxc));
284 pit8253.out_handler<2>().set("pic8259_0", FUNC(pic8259_device::ir0_w));
285
286 pic8259_device &pic8259_0(PIC8259(config, "pic8259_0"));
287 pic8259_0.out_int_callback().set_inputline(m_maincpu, 0);
288 pic8259_0.in_sp_callback().set_constant(1);
289 pic8259_0.read_slave_ack_callback().set(FUNC(peoplepc_state::get_slave_ack));
290
291 PIC8259(config, m_pic_1);
292 m_pic_1->out_int_callback().set("pic8259_0", FUNC(pic8259_device::ir7_w));
293 m_pic_1->in_sp_callback().set_constant(0);
294
295 I8255(config, "ppi8255");
296
297 screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER, rgb_t::green()));
298 screen.set_raw(XTAL(22'000'000), 640, 0, 640, 475, 0, 475);
299 screen.set_screen_update("h46505", FUNC(mc6845_device::screen_update));
300
301 GFXDECODE(config, m_gfxdecode, m_palette, gfxdecode_device::empty);
302 PALETTE(config, m_palette, palette_device::MONOCHROME);
303
304 HD6845S(config, m_crtc, XTAL(22'000'000)/8); // HD46505SP according to User's Guide
305 m_crtc->set_screen("screen");
306 m_crtc->set_show_border_area(false);
307 m_crtc->set_char_width(8);
308 m_crtc->set_update_row_callback(FUNC(peoplepc_state::update_row));
309
310 I8257(config, m_dmac, XTAL(14'745'600)/3);
311 m_dmac->out_hrq_cb().set(FUNC(peoplepc_state::hrq_w));
312 m_dmac->out_tc_cb().set(FUNC(peoplepc_state::tc_w));
313 m_dmac->in_memr_cb().set(FUNC(peoplepc_state::memory_read_byte));
314 m_dmac->out_memw_cb().set(FUNC(peoplepc_state::memory_write_byte));
315 m_dmac->in_ior_cb<0>().set("upd765", FUNC(upd765a_device::dma_r));
316 m_dmac->out_iow_cb<0>().set("upd765", FUNC(upd765a_device::dma_w));
317
318 UPD765A(config, m_fdc, XTAL(8'000'000)/2, true, true);
319 m_fdc->intrq_wr_callback().set("pic8259_0", FUNC(pic8259_device::ir2_w));
320 m_fdc->drq_wr_callback().set(m_dmac, FUNC(i8257_device::dreq0_w));
321 FLOPPY_CONNECTOR(config, "upd765:0", peoplepc_floppies, "525qd", peoplepc_state::floppy_formats);
322 FLOPPY_CONNECTOR(config, "upd765:1", peoplepc_floppies, "525qd", peoplepc_state::floppy_formats);
323
324 I8251(config, m_8251key, XTAL(14'745'600)/6);
325 m_8251key->rxrdy_handler().set("pic8259_1", FUNC(pic8259_device::ir1_w));
326 m_8251key->txd_handler().set("kbd", FUNC(rs232_port_device::write_txd));
327
328 rs232_port_device &kbd(RS232_PORT(config, "kbd", peoplepc_keyboard_devices, "keyboard"));
329 kbd.rxd_handler().set(m_8251key, FUNC(i8251_device::write_rxd));
330 kbd.set_option_device_input_defaults("keyboard", DEVICE_INPUT_DEFAULTS_NAME(keyboard));
331
332 I8048(config, "kbdmcu", 4'608'000).set_disable(); // XTAL unknown
333
334 I8251(config, m_8251ser, XTAL(14'745'600)/6);
335 m_8251ser->rxrdy_handler().set("pic8259_0", FUNC(pic8259_device::ir5_w));
336 m_8251ser->txrdy_handler().set("pic8259_0", FUNC(pic8259_device::ir6_w));
337 m_8251ser->txd_handler().set("rs232c", FUNC(rs232_port_device::write_txd));
338 m_8251ser->rts_handler().set("rs232c", FUNC(rs232_port_device::write_rts));
339 m_8251ser->dtr_handler().set("rs232c", FUNC(rs232_port_device::write_dtr));
340
341 rs232_port_device &rs232c(RS232_PORT(config, "rs232c", default_rs232_devices, nullptr));
342 rs232c.rxd_handler().set(m_8251ser, FUNC(i8251_device::write_rxd));
343 rs232c.dsr_handler().set(m_8251ser, FUNC(i8251_device::write_dsr));
344 rs232c.cts_handler().set(m_8251ser, FUNC(i8251_device::write_cts));
345 }
346
347 ROM_START( olypeopl )
348 ROM_REGION(0x2000, "maincpu", 0)
349 ROM_SYSTEM_BIOS(0, "hd", "HD ROM")
350 ROMX_LOAD( "u01271c0.bin", 0x00000, 0x1000, CRC(8e0ef114) SHA1(774bab0a3e29853e9f6b951cf73082063ea61e6d), ROM_SKIP(1) | ROM_BIOS(0))
351 ROMX_LOAD( "u01271d0.bin", 0x00001, 0x1000, CRC(e2419bf9) SHA1(d88381f8709c91e2adba08f378e29bd0d19ee5ae), ROM_SKIP(1) | ROM_BIOS(0))
352 ROM_SYSTEM_BIOS(1, "2fd", "2 FD ROM")
353 ROMX_LOAD( "u01277f3.bin", 0x00000, 0x1000, CRC(428ff135) SHA1(ec11f0e43455570c40f5dc4b84f8420da5939368), ROM_SKIP(1) | ROM_BIOS(1))
354 ROMX_LOAD( "u01277g3.bin", 0x00001, 0x1000, CRC(3295691c) SHA1(7d7ade62117d11656b8dd86cf0703127616d55bc), ROM_SKIP(1) | ROM_BIOS(1))
355
356 ROM_REGION(0x400, "kbdmcu", 0)
357 ROM_LOAD( "m1.bin", 0x000, 0x400, NO_DUMP )
358 ROM_END
359
360 COMP( 1983, olypeopl, 0, 0, olypeopl, 0, peoplepc_state, empty_init, "Olympia", "People PC", MACHINE_NOT_WORKING|MACHINE_NO_SOUND)
361