Previous 199869 Revisions Next

r23871 Sunday 23rd June, 2013 at 10:11:17 UTC by Robbbert
(MESS) H8 : added code for cassette, paste. Added the official test program code for pasting.
[src/mess/drivers]h8.c

trunk/src/mess/drivers/h8.c
r23870r23871
22
33        Heathkit H8
44
5        12/05/2009 Skeleton driver.
5        2009-05-12 Skeleton driver.
66
7    STATUS:
8    - It runs, keyboard works, you can enter data
7        This system uses Octal rather than the usual hexadecimal.
98
10    TODO:
11    - Proper artwork
12    - Fix interrupts
13    - Seems to crash when GO pressed (needs a subject-matter expert to test)
14    - Add load/dump facility (cassette port)
9STATUS:
10        It runs, keyboard works, you can enter data.
1511
12Meaning of LEDs:
13        PWR = power is turned on
14        MON = controls should work
15        RUN = CPU is running (not halted)
16        ION = Interrupts are enabled
17
18Pasting:
19        0-F : as is
20        + : ^
21        - : V
22        MEM : -
23        ALTER : =
24
25        Addresses must have all 6 digits entered.
26        Data must have all 3 digits entered.
27        System has a short beep for each key, and a slightly longer beep
28            for each group of 3 digits. The largest number allowed is 377 (=0xFF).
29
30Test Paste:
31        -041000=123 245 333 144 255 366 077=-041000
32        Now press up-arrow to confirm the data has been entered.
33
34Official test program from pages 4 to 8 of the operator's manual:
35        -040100=076 002 062 010 040 006 004 041 170 040 021 013 040 016 011 176
36                022 043 023 015 302 117 040 016 003 076 377 315 053 000 015 302
37                131 040 005 302 112 040 076 062 315 140 002 076 062 315 053 000
38                076 062 315 140 002 303 105 040 377 262 270 272 275 377 222 200
39                377 237 244 377 272 230 377 220 326 302 377 275 272 271 271 373
40                271 240 377 236 376 362 236 376 362 236 376 362 R6=040100=4
41
42TODO:
43        - Cassette (coded but not working)
44
1645****************************************************************************/
1746
1847#include "emu.h"
1948#include "cpu/i8085/i8085.h"
49#include "machine/i8251.h"
50#include "imagedev/cassette.h"
2051#include "sound/beep.h"
52#include "sound/wave.h"
2153#include "h8.lh"
2254
2355
r23870r23871
2658public:
2759   h8_state(const machine_config &mconfig, device_type type, const char *tag)
2860      : driver_device(mconfig, type, tag),
29   m_maincpu(*this, "maincpu"),
30   //m_cass(*this, "cassette"),
31   m_beep(*this, "beeper")
61      m_maincpu(*this, "maincpu"),
62      m_uart(*this, "uart"),
63      m_cass(*this, "cassette"),
64      m_beep(*this, "beeper")
3265   { }
3366
34   required_device<cpu_device> m_maincpu;
35   //required_device<cassette_image_device> m_cass;
36   required_device<beep_device> m_beep;
37   DECLARE_READ8_MEMBER(h8_f0_r);
38   DECLARE_WRITE8_MEMBER(h8_f0_w);
39   DECLARE_WRITE8_MEMBER(h8_f1_w);
67   DECLARE_READ8_MEMBER(portf0_r);
68   DECLARE_WRITE8_MEMBER(portf0_w);
69   DECLARE_WRITE8_MEMBER(portf1_w);
4070   DECLARE_WRITE8_MEMBER(h8_status_callback);
4171   DECLARE_WRITE_LINE_MEMBER(h8_inte_callback);
72   DECLARE_READ_LINE_MEMBER(rxdata_callback);
73   DECLARE_WRITE_LINE_MEMBER(txdata_callback);
74   TIMER_DEVICE_CALLBACK_MEMBER(h8_irq_pulse);
75   TIMER_DEVICE_CALLBACK_MEMBER(h8_c);
76   TIMER_DEVICE_CALLBACK_MEMBER(h8_p);
77private:
4278   UINT8 m_digit;
4379   UINT8 m_segment;
4480   UINT8 m_irq_ctl;
45   UINT8 m_ff_b;
81   bool m_ff_b;
82   UINT8 m_cass_data[4];
83   bool m_cass_state;
4684   virtual void machine_reset();
47   TIMER_DEVICE_CALLBACK_MEMBER(h8_irq_pulse);
85   required_device<cpu_device> m_maincpu;
86   required_device<i8251_device> m_uart;
87   required_device<cassette_image_device> m_cass;
88   required_device<beep_device> m_beep;
4889};
4990
5091
r23870r23871
59100      m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xcf);
60101}
61102
62READ8_MEMBER( h8_state::h8_f0_r )
103READ8_MEMBER( h8_state::portf0_r )
63104{
64105   // reads the keyboard
65106
r23870r23871
89130   return data;
90131}
91132
92WRITE8_MEMBER( h8_state::h8_f0_w )
133WRITE8_MEMBER( h8_state::portf0_w )
93134{
94135   // this will always turn off int10 that was set by the timer
95136   // d0-d3 = digit select
r23870r23871
101142   m_digit = data & 15;
102143   if (m_digit) output_set_digit_value(m_digit, m_segment);
103144
104   output_set_value("mon_led",(data & 0x20) ? 0 : 1);
105   m_beep->set_state((data & 0x80) ? 0 : 1);
145   output_set_value("mon_led", !BIT(data, 5));
146   m_beep->set_state(!BIT(data, 7));
106147
107148   m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
108149   m_irq_ctl &= 0xf0;
109   if (data & 0x40) m_irq_ctl |= 1;
110   if (~data & 0x10) m_irq_ctl |= 2;
150   if (BIT(data, 6)) m_irq_ctl |= 1;
151   if (!BIT(data, 4)) m_irq_ctl |= 2;
111152}
112153
113WRITE8_MEMBER( h8_state::h8_f1_w )
154WRITE8_MEMBER( h8_state::portf1_w )
114155{
115156   //d7 segment dot
116157   //d6 segment f
r23870r23871
127168
128169static ADDRESS_MAP_START(h8_mem, AS_PROGRAM, 8, h8_state)
129170   ADDRESS_MAP_UNMAP_HIGH
130   AM_RANGE(0x0000, 0x03ff) AM_ROM
171   AM_RANGE(0x0000, 0x0fff) AM_ROM
131172   AM_RANGE(0x2000, 0x9fff) AM_RAM
132173ADDRESS_MAP_END
133174
134175static ADDRESS_MAP_START( h8_io, AS_IO, 8, h8_state)
135176   ADDRESS_MAP_UNMAP_HIGH
136177   ADDRESS_MAP_GLOBAL_MASK(0xff)
137   AM_RANGE(0xf0, 0xf0) AM_READWRITE(h8_f0_r,h8_f0_w)
138   AM_RANGE(0xf1, 0xf1) AM_WRITE(h8_f1_w)
139   //AM_RANGE(0xf8, 0xf8) load and dump data port
140   //AM_RANGE(0xf9, 0xf9) load and dump control port
141   //AM_RANGE(0xfa, 0xfa) console data port
142   //AM_RANGE(0xfb, 0xfb) console control port
178   AM_RANGE(0xf0, 0xf0) AM_READWRITE(portf0_r,portf0_w)
179   AM_RANGE(0xf1, 0xf1) AM_WRITE(portf1_w)
180   AM_RANGE(0xf8, 0xf8) AM_DEVREADWRITE("uart", i8251_device, data_r, data_w)
181   AM_RANGE(0xf9, 0xf9) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w)
182   // optional connection to a serial terminal @ 600 baud
183   //AM_RANGE(0xfa, 0xfa) AM_DEVREADWRITE("uart1", i8251_device, data_r, data_w)
184   //AM_RANGE(0xfb, 0xfb) AM_DEVREADWRITE("uart1", i8251_device, status_r, control_w)
143185ADDRESS_MAP_END
144186
145187/* Input ports */
r23870r23871
157199   PORT_START("X1")
158200   PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("8 LOAD") PORT_CODE(KEYCODE_8) PORT_CHAR('8')
159201   PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("9 DUMP") PORT_CODE(KEYCODE_9) PORT_CHAR('9')
160   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("+") PORT_CODE(KEYCODE_EQUALS)
161   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS)
162   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("* CANCEL") PORT_CODE(KEYCODE_Q)
163   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("// ALTER RST") PORT_CODE(KEYCODE_W)
164   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("# MEM RTM") PORT_CODE(KEYCODE_E)
165   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("@ REG") PORT_CODE(KEYCODE_R)
202   PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("+") PORT_CODE(KEYCODE_UP) PORT_CHAR('^')
203   PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_DOWN) PORT_CHAR('V')
204   PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CANCEL") PORT_CODE(KEYCODE_ESC) PORT_CHAR('Q')
205   PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ALTER") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=')
206   PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("MEM") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
207   PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("REG") PORT_CODE(KEYCODE_R) PORT_CHAR('R')
166208INPUT_PORTS_END
167209
168210void h8_state::machine_reset()
r23870r23871
170212   m_beep->set_frequency(H8_BEEP_FRQ);
171213   output_set_value("pwr_led", 0);
172214   m_irq_ctl = 1;
215   m_cass_state = 1;
216   m_cass_data[0] = 0;
217   m_cass_data[1] = 0;
218   m_cass_data[2] = 0;
219   m_cass_data[3] = 0;
173220}
174221
175222WRITE_LINE_MEMBER( h8_state::h8_inte_callback )
176223{
177224      // operate the ION LED
178   output_set_value("ion_led",(state) ? 0 : 1);
225   output_set_value("ion_led", !state);
179226   m_irq_ctl &= 0x7f | ((state) ? 0 : 0x80);
180227}
181228
r23870r23871
186233a int20 (output of 2nd flipflop) will occur after 4 M1 steps, to pause the running program.
187234But, all of this can only occur if bit 5 of port F0 is low. */
188235
189   UINT8 state = (data & I8085_STATUS_M1) ? 0 : 1;
190   UINT8 c,a = (m_irq_ctl & 0x80) ? 1 : 0;
236   bool state = (data & I8085_STATUS_M1) ? 0 : 1;
237   bool c,a = (m_irq_ctl & 0x80) ? 1 : 0;
191238
192239   if (m_irq_ctl & 2)
193240   {
194241      if (!state) // rising pulse to push data through flipflops
195242      {
196         c=m_ff_b^1; // from /Q of 2nd flipflop
197         m_ff_b=a; // from Q of 1st flipflop
243         c = ~m_ff_b; // from /Q of 2nd flipflop
244         m_ff_b = a; // from Q of 1st flipflop
198245         if (c)
199246            m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xd7);
200247      }
201248   }
202249   else
203250   { // flipflops are 'set'
204      c=0;
205      m_ff_b=1;
251      c = 0;
252      m_ff_b = 1;
206253   }
207254
208255
r23870r23871
210257   output_set_value("run_led", state);
211258}
212259
260READ_LINE_MEMBER( h8_state::rxdata_callback )
261{//printf("%X",m_cass_data[2]);
262   return (bool)m_cass_data[2];
263}
264
265WRITE_LINE_MEMBER( h8_state::txdata_callback )
266{
267   m_cass_state = state;
268}
269
270static const i8251_interface uart_intf =
271{
272   DEVCB_DRIVER_LINE_MEMBER(h8_state,rxdata_callback), //rxd_cb
273   DEVCB_DRIVER_LINE_MEMBER(h8_state,txdata_callback), //txd_cb
274   DEVCB_NULL,
275   DEVCB_NULL,
276   DEVCB_NULL,
277   DEVCB_NULL,
278   DEVCB_NULL,
279   DEVCB_NULL,
280   DEVCB_NULL
281};
282
213283static I8085_CONFIG( h8_cpu_config )
214284{
215285   DEVCB_DRIVER_MEMBER(h8_state, h8_status_callback),      /* Status changed callback */
r23870r23871
218288   DEVCB_NULL                  /* SOD changed callback (I8085A only) */
219289};
220290
291TIMER_DEVICE_CALLBACK_MEMBER(h8_state::h8_c)
292{
293   m_uart->receive_clock();
294   m_uart->transmit_clock();
295   m_cass_data[3]++;
296
297   if (m_cass_state)
298      m_cass->output(BIT(m_cass_data[3], 0) ? -1.0 : +1.0); // 2400Hz
299   else
300      m_cass->output(BIT(m_cass_data[3], 1) ? -1.0 : +1.0); // 1200Hz
301}
302
303TIMER_DEVICE_CALLBACK_MEMBER(h8_state::h8_p)
304{
305   /* cassette - turn 1200/2400Hz to a bit */
306   m_cass_data[1]++;
307   UINT8 cass_ws = (m_cass->input() > +0.03) ? 1 : 0;
308
309   if (cass_ws != m_cass_data[0])
310   {
311      m_cass_data[0] = cass_ws;
312      m_cass_data[2] = (m_cass_data[1] < 12) ? 1 : 0;
313      m_cass_data[1] = 0;
314   }
315}
316
317static const cassette_interface h8_cassette_interface =
318{
319   cassette_default_formats,
320   NULL,
321   //(cassette_state) (CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_ENABLED),
322   (cassette_state) (CASSETTE_PLAY | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED),
323   "h8_cass",
324   NULL
325};
326
221327static MACHINE_CONFIG_START( h8, h8_state )
222328   /* basic machine hardware */
223329   MCFG_CPU_ADD("maincpu", I8080, H8_CLOCK)
r23870r23871
225331   MCFG_CPU_IO_MAP(h8_io)
226332   MCFG_CPU_CONFIG(h8_cpu_config)
227333
228   MCFG_TIMER_DRIVER_ADD_PERIODIC("h8_timer", h8_state, h8_irq_pulse, attotime::from_hz(H8_IRQ_PULSE))
229
230334   /* video hardware */
231335   MCFG_DEFAULT_LAYOUT(layout_h8)
232336
r23870r23871
234338   MCFG_SPEAKER_STANDARD_MONO("mono")
235339   MCFG_SOUND_ADD("beeper", BEEP, 0)
236340   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
341   MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
342   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
343
344   /* Devices */
345   MCFG_I8251_ADD("uart", uart_intf)
346   MCFG_CASSETTE_ADD("cassette", h8_cassette_interface)
347   MCFG_TIMER_DRIVER_ADD_PERIODIC("h8_c", h8_state, h8_c, attotime::from_hz(4800))
348   MCFG_TIMER_DRIVER_ADD_PERIODIC("h8_p", h8_state, h8_p, attotime::from_hz(40000))
349   MCFG_TIMER_DRIVER_ADD_PERIODIC("h8_timer", h8_state, h8_irq_pulse, attotime::from_hz(H8_IRQ_PULSE))
237350MACHINE_CONFIG_END
238351
239352/* ROM definition */
r23870r23871
251364
252365/* Driver */
253366
254/*    YEAR  NAME    PARENT  COMPAT   MACHINE    INPUT    INIT    COMPANY   FULLNAME       FLAGS */
255COMP( 1977, h8,  0,       0,    h8,     h8, driver_device,   0, "Heath, Inc.", "Heathkit H8", GAME_NOT_WORKING )
367/*    YEAR  NAME PARENT  COMPAT MACHINE INPUT    CLASS,         INIT    COMPANY       FULLNAME       FLAGS */
368COMP( 1977, h8,  0,       0,    h8,     h8,      driver_device,   0, "Heath, Inc.", "Heathkit H8", GAME_NOT_WORKING )

Previous 199869 Revisions Next


© 1997-2024 The MAME Team