1 // license:BSD-3-Clause
2 // copyright-holders:Robbbert
3 /***************************************************************************
4 
5     Babbage-2nd skeleton driver (19/OCT/2011)
6 
7     http://takeda-toshiya.my.coocan.jp/babbage/index.html
8 
9     Pasting:
10         0-F : as is
11         INC : ^
12         AD : -
13         DA : =
14         GO : X
15 
16     Here is a test program to turn on the LEDs.
17     Copy the text and Paste into the emulator.
18     =3E^=0F^=D3^=13^=3E^=07^=D3^=13^=3E^=00^=D3^=12^=76^-1000X
19 
20 
21 ***************************************************************************/
22 
23 #include "emu.h"
24 #include "cpu/z80/z80.h"
25 #include "machine/timer.h"
26 #include "machine/z80ctc.h"
27 #include "machine/z80pio.h"
28 #include "machine/z80daisy.h"
29 #include "video/pwm.h"
30 #include "babbage.lh"
31 
32 #define MAIN_CLOCK 25e5
33 
34 class babbage_state : public driver_device
35 {
36 public:
babbage_state(const machine_config & mconfig,device_type type,const char * tag)37 	babbage_state(const machine_config &mconfig, device_type type, const char *tag)
38 		: driver_device(mconfig, type, tag)
39 		, m_maincpu(*this, "maincpu")
40 		, m_pio(*this, "z80pio_%u", 1U)
41 		, m_ctc(*this, "z80ctc")
42 		, m_display(*this, "display")
43 		, m_io_keyboard(*this, "X%u", 0U)
44 		, m_leds(*this, "led%u", 0U)
45 	{ }
46 
47 	void babbage(machine_config &config);
48 
49 protected:
50 	virtual void machine_start() override;
51 
52 private:
53 	uint8_t pio2_a_r();
54 	void pio1_b_w(uint8_t data);
55 	void pio2_b_w(uint8_t data);
56 	DECLARE_WRITE_LINE_MEMBER(ctc_z0_w);
57 	DECLARE_WRITE_LINE_MEMBER(ctc_z1_w);
58 	DECLARE_WRITE_LINE_MEMBER(ctc_z2_w);
59 	TIMER_DEVICE_CALLBACK_MEMBER(keyboard_callback);
60 
61 	void babbage_io(address_map &map);
62 	void babbage_map(address_map &map);
63 
64 	uint8_t m_seg;
65 	uint8_t m_key;
66 	uint8_t m_prev_key;
67 	bool m_step;
68 
69 	required_device<z80_device> m_maincpu;
70 	required_device_array<z80pio_device, 2> m_pio;
71 	required_device<z80ctc_device> m_ctc;
72 	required_device<pwm_display_device> m_display;
73 	required_ioport_array<4> m_io_keyboard;
74 	output_finder<8> m_leds;
75 };
76 
77 
78 
79 /***************************************************************************
80 
81     Address Map
82 
83 ***************************************************************************/
84 
babbage_map(address_map & map)85 void babbage_state::babbage_map(address_map &map)
86 {
87 	map.global_mask(0x3fff);
88 	map(0x0000, 0x07ff).rom();
89 	map(0x1000, 0x17ff).ram();
90 }
91 
babbage_io(address_map & map)92 void babbage_state::babbage_io(address_map &map)
93 {
94 	map.global_mask(0xff);
95 	map(0x00, 0x03).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
96 	map(0x10, 0x13).rw(m_pio[0], FUNC(z80pio_device::read_alt), FUNC(z80pio_device::write_alt));
97 	map(0x20, 0x23).rw(m_pio[1], FUNC(z80pio_device::read_alt), FUNC(z80pio_device::write_alt));
98 }
99 
100 
101 
102 /**************************************************************************
103 
104     Keyboard Layout
105 
106 ***************************************************************************/
107 
108 // no idea of the actual key matrix
109 static INPUT_PORTS_START( babbage )
110 	PORT_START("X0")
PORT_CODE(KEYCODE_0)111 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
112 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4')
113 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8')
114 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C')
115 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("GO") PORT_CODE(KEYCODE_X) PORT_CHAR('X')
116 
117 	PORT_START("X1")
118 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1')
119 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5')
120 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9')
121 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D')
122 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("AD") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
123 
124 	PORT_START("X2")
125 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2')
126 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6')
127 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A')
128 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E')
129 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DA") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=')
130 
131 	PORT_START("X3")
132 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3')
133 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7')
134 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B')
135 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F')
136 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("INC") PORT_CODE(KEYCODE_UP) PORT_CHAR('^')
137 INPUT_PORTS_END
138 
139 /* Z80-CTC Interface */
140 
141 WRITE_LINE_MEMBER( babbage_state::ctc_z0_w )
142 {
143 }
144 
WRITE_LINE_MEMBER(babbage_state::ctc_z1_w)145 WRITE_LINE_MEMBER( babbage_state::ctc_z1_w )
146 {
147 }
148 
WRITE_LINE_MEMBER(babbage_state::ctc_z2_w)149 WRITE_LINE_MEMBER( babbage_state::ctc_z2_w )
150 {
151 }
152 
153 /* Z80-PIO Interface */
154 
155 // The 8 LEDs
156 // bios never writes here - you need to set PIO for output yourself - see test program above
pio1_b_w(uint8_t data)157 void babbage_state::pio1_b_w(uint8_t data)
158 {
159 	for (int i = 0; i < 8; i++)
160 		m_leds[i] = BIT(data, i);
161 }
162 
pio2_a_r()163 uint8_t babbage_state::pio2_a_r()
164 {
165 	if (!machine().side_effects_disabled())
166 		m_maincpu->set_input_line(0, CLEAR_LINE); // release interrupt
167 	return m_key;
168 }
169 
pio2_b_w(uint8_t data)170 void babbage_state::pio2_b_w(uint8_t data)
171 {
172 	if (BIT(data, 7))
173 		m_step = false;
174 	else
175 	if (!m_step)
176 	{
177 		m_seg = data;
178 		m_step = true;
179 	}
180 	else
181 		m_display->matrix(data, m_seg);
182 }
183 
184 static const z80_daisy_config babbage_daisy_chain[] =
185 {// need to check the order
186 	{ "z80pio_1" },
187 	{ "z80pio_2" },
188 	{ "z80ctc" },
189 	{ nullptr }
190 };
191 
TIMER_DEVICE_CALLBACK_MEMBER(babbage_state::keyboard_callback)192 TIMER_DEVICE_CALLBACK_MEMBER(babbage_state::keyboard_callback)
193 {
194 	u8 inp, data = 0xff;
195 
196 	for (u8 i = 0; i < 4; i++)
197 	{
198 		inp = m_io_keyboard[i]->read();
199 
200 		for (u8 j = 0; j < 5; j++)
201 			if (BIT(inp, j))
202 				data = (j << 2) | i;
203 	}
204 
205 	/* make sure only one keystroke */
206 	if (data != m_prev_key)
207 		m_prev_key = data;
208 	else
209 		data = 0xff;
210 
211 	/* while key is down, activate strobe. When key released, deactivate strobe which causes an interrupt */
212 	if (data < 0xff)
213 	{
214 		m_key = data;
215 		m_pio[1]->strobe(0, 0);
216 	}
217 	else
218 		m_pio[1]->strobe(0, 1);
219 }
220 
machine_start()221 void babbage_state::machine_start()
222 {
223 	m_leds.resolve();
224 
225 	save_item(NAME(m_seg));
226 	save_item(NAME(m_key));
227 	save_item(NAME(m_prev_key));
228 	save_item(NAME(m_step));
229 }
230 
231 /***************************************************************************
232 
233     Machine driver
234 
235 ***************************************************************************/
236 
babbage(machine_config & config)237 void babbage_state::babbage(machine_config &config)
238 {
239 	/* basic machine hardware */
240 	Z80(config, m_maincpu, MAIN_CLOCK); //2.5MHz
241 	m_maincpu->set_addrmap(AS_PROGRAM, &babbage_state::babbage_map);
242 	m_maincpu->set_addrmap(AS_IO, &babbage_state::babbage_io);
243 	m_maincpu->set_daisy_config(babbage_daisy_chain);
244 
245 	/* video hardware */
246 	config.set_default_layout(layout_babbage);
247 	PWM_DISPLAY(config, m_display).set_size(6, 8);
248 	m_display->set_segmask(0x3f, 0xff);
249 
250 	/* Devices */
251 	Z80CTC(config, m_ctc, MAIN_CLOCK);
252 	m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
253 	m_ctc->zc_callback<0>().set(FUNC(babbage_state::ctc_z0_w));
254 	m_ctc->zc_callback<1>().set(FUNC(babbage_state::ctc_z1_w));
255 	m_ctc->zc_callback<2>().set(FUNC(babbage_state::ctc_z2_w));
256 
257 	Z80PIO(config, m_pio[0], MAIN_CLOCK);
258 	m_pio[0]->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
259 	m_pio[0]->out_pb_callback().set(FUNC(babbage_state::pio1_b_w));
260 
261 	Z80PIO(config, m_pio[1], MAIN_CLOCK);
262 	m_pio[1]->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
263 	m_pio[1]->in_pa_callback().set(FUNC(babbage_state::pio2_a_r));
264 	m_pio[1]->out_pb_callback().set(FUNC(babbage_state::pio2_b_w));
265 
266 	TIMER(config, "keyboard_timer", 0).configure_periodic(FUNC(babbage_state::keyboard_callback), attotime::from_hz(30));
267 }
268 
269 
270 /***************************************************************************
271 
272     Game driver
273 
274 ***************************************************************************/
275 
276 ROM_START(babbage)
277 	ROM_REGION(0x0800, "maincpu", ROMREGION_ERASEFF)
278 	ROM_LOAD("mon.rom",    0x0000, 0x0200, CRC(469bd607) SHA1(8f3489a0f96de6a03b05c1ee01b89d9848f4b152) )
279 ROM_END
280 
281 
282 //    YEAR  NAME     PARENT  COMPAT  MACHINE  INPUT    CLASS          INIT        COMPANY               FULLNAME       FLAGS
283 COMP( 1986, babbage, 0,      0,      babbage, babbage, babbage_state, empty_init, "Mr Takafumi Aihara", "Babbage-2nd", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE )
284