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