summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/kaypro.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/kaypro.cpp')
-rw-r--r--src/mame/machine/kaypro.cpp292
1 files changed, 292 insertions, 0 deletions
diff --git a/src/mame/machine/kaypro.cpp b/src/mame/machine/kaypro.cpp
new file mode 100644
index 00000000000..9b9c3a7bab7
--- /dev/null
+++ b/src/mame/machine/kaypro.cpp
@@ -0,0 +1,292 @@
+// license:BSD-3-Clause
+// copyright-holders:Robbbert
+
+
+#include "includes/kaypro.h"
+
+
+
+
+/***********************************************************
+
+ PIO
+
+ Port B is unused on both PIOs
+
+************************************************************/
+
+WRITE_LINE_MEMBER( kaypro_state::write_centronics_busy )
+{
+ m_centronics_busy = state;
+}
+
+READ8_MEMBER( kaypro_state::pio_system_r )
+{
+ UINT8 data = 0;
+
+ /* centronics busy */
+ data |= m_centronics_busy << 3;
+
+ /* PA7 is pulled high */
+ data |= 0x80;
+
+ return data;
+}
+
+WRITE8_MEMBER( kaypro_state::kayproii_pio_system_w )
+{
+/* d7 bank select
+ d6 disk drive motors - (0=on)
+ d5 double-density enable (0=double density)
+ d4 Centronics strobe
+ d2 side select (1=side 1)
+ d1 drive B
+ d0 drive A */
+
+ membank("bankr0")->set_entry(BIT(data, 7));
+ membank("bank3")->set_entry(BIT(data, 7));
+ m_is_motor_off = BIT(data, 6);
+
+ m_floppy = NULL;
+ if (BIT(data, 0))
+ m_floppy = m_floppy0->get_device();
+ else
+ if (BIT(data, 1))
+ m_floppy = m_floppy1->get_device();
+
+ m_fdc->set_floppy(m_floppy);
+ m_fdc->dden_w(BIT(data, 5));
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w(BIT(data, 6)); // motor on
+ m_floppy->ss_w(!BIT(data, 2)); // signal exists even though drives are single sided
+ }
+
+ output_set_value("ledA", BIT(data, 0)); /* LEDs in artwork */
+ output_set_value("ledB", BIT(data, 1));
+
+ m_centronics->write_strobe(BIT(data, 4));
+
+ m_system_port = data;
+}
+
+WRITE8_MEMBER( kaypro_state::kaypro4_pio_system_w )
+{
+ kayproii_pio_system_w(space, offset, data);
+
+ /* side select */
+ m_floppy->ss_w(BIT(data, 2));
+}
+
+/***********************************************************
+
+ KAYPRO2X SYSTEM PORT
+
+ The PIOs were replaced by a few standard 74xx chips
+
+************************************************************/
+
+READ8_MEMBER( kaypro_state::kaypro2x_system_port_r )
+{
+ UINT8 data = m_centronics_busy << 6;
+ return (m_system_port & 0xbf) | data;
+}
+
+WRITE8_MEMBER( kaypro_state::kaypro2x_system_port_w )
+{
+/* d7 bank select
+ d6 alternate character set (write only)
+ d5 double-density enable
+ d4 disk drive motors (1=on)
+ d3 Centronics strobe
+ d2 side select (appears that 0=side 1?)
+ d1 drive B
+ d0 drive A */
+
+ membank("bankr0")->set_entry(BIT(data, 7));
+ membank("bank3")->set_entry(BIT(data, 7));
+ m_is_motor_off = !BIT(data, 4);
+
+ m_floppy = NULL;
+ if (!BIT(data, 0))
+ m_floppy = m_floppy0->get_device();
+ else
+ if (m_floppy1 && (!BIT(data, 1)))
+ m_floppy = m_floppy1->get_device();
+
+ m_fdc->set_floppy(m_floppy);
+ m_fdc->dden_w(BIT(data, 5));
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w(!BIT(data, 4)); // motor on
+ m_floppy->ss_w(!BIT(data, 2));
+ }
+
+ output_set_value("ledA", BIT(data, 0)); /* LEDs in artwork */
+ output_set_value("ledB", BIT(data, 1));
+
+ m_centronics->write_strobe(BIT(data, 3));
+
+ m_system_port = data;
+}
+
+
+/***********************************************************************
+
+ SIO
+
+ On Kaypro2x, Channel B on both SIOs is hardwired to 300 baud.
+
+ Both devices on sio2 (printer and modem) are not emulated.
+
+************************************************************************/
+
+/* Set baud rate. bits 0..3 Rx and Tx are tied together. Baud Rate Generator is a AY-5-8116, SMC8116, WD1943, etc.
+ 00h 50
+ 11h 75
+ 22h 110
+ 33h 134.5
+ 44h 150
+ 55h 300
+ 66h 600
+ 77h 1200
+ 88h 1800
+ 99h 2000
+ AAh 2400
+ BBh 3600
+ CCh 4800
+ DDh 7200
+ EEh 9600
+ FFh 19200 */
+
+
+READ8_MEMBER(kaypro_state::kaypro_sio_r)
+{
+ if (offset == 1)
+ return kay_kbd_d_r(machine());
+ else
+ if (offset == 3)
+ return kay_kbd_c_r(machine());
+ else
+ return m_sio->cd_ba_r(space, offset);
+}
+
+WRITE8_MEMBER(kaypro_state::kaypro_sio_w)
+{
+ if (offset == 1)
+ kay_kbd_d_w(machine(), data);
+ else
+ m_sio->cd_ba_w(space, offset, data);
+}
+
+
+/*************************************************************************************
+
+ Floppy DIsk
+
+ If DRQ or IRQ is set, and cpu is halted, the NMI goes low.
+ Since the HALT occurs last (and has no callback mechanism), we need to set
+ a short delay, to give time for the processor to execute the HALT before NMI
+ becomes active.
+
+*************************************************************************************/
+
+void kaypro_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ bool halt;
+ switch (id)
+ {
+ case TIMER_FLOPPY:
+ halt = (bool)m_maincpu->state_int(Z80_HALT);
+ if (m_is_motor_off)
+ {
+ timer_set(attotime::from_hz(10), TIMER_FLOPPY);
+ break;
+ }
+ if ((halt) && (m_fdc_rq & 3) && (m_fdc_rq < 0x80))
+ {
+ m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
+ m_fdc_rq |= 0x80;
+ }
+ else
+ if ((m_fdc_rq == 0x80) || ((!halt) && BIT(m_fdc_rq, 7)))
+ {
+ m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
+ m_fdc_rq &= 0x7f;
+ }
+ timer_set(attotime::from_hz(1e5), TIMER_FLOPPY);
+
+ break;
+ default:
+ assert_always(FALSE, "Unknown id in kaypro_state::device_timer");
+ }
+}
+
+WRITE_LINE_MEMBER( kaypro_state::fdc_intrq_w )
+{
+ m_fdc_rq = (m_fdc_rq & 0x82) | state;
+}
+
+WRITE_LINE_MEMBER( kaypro_state::fdc_drq_w )
+{
+ m_fdc_rq = (m_fdc_rq & 0x81) | (state << 1);
+}
+
+
+/***********************************************************
+
+ Machine
+
+************************************************************/
+MACHINE_START_MEMBER( kaypro_state,kayproii )
+{
+ m_pio_s->strobe_a(0);
+}
+
+MACHINE_RESET_MEMBER( kaypro_state,kaypro )
+{
+ MACHINE_RESET_CALL_MEMBER(kay_kbd);
+ membank("bankr0")->set_entry(1); // point at rom
+ membank("bankw0")->set_entry(0); // always write to ram
+ membank("bank3")->set_entry(1); // point at video ram
+ m_system_port = 0x80;
+ m_fdc_rq = 0;
+ m_maincpu->reset();
+ timer_set(attotime::from_hz(1), TIMER_FLOPPY); /* kick-start the nmi timer */
+}
+
+
+/***********************************************************
+
+ Quickload
+
+ This loads a .COM file to address 0x100 then jumps
+ there. Sometimes .COM has been renamed to .CPM to
+ prevent windows going ballistic. These can be loaded
+ as well.
+
+************************************************************/
+
+QUICKLOAD_LOAD_MEMBER( kaypro_state, kaypro )
+{
+ UINT8 *RAM = memregion("rambank")->base();
+ UINT16 i;
+ UINT8 data;
+
+ /* Load image to the TPA (Transient Program Area) */
+ for (i = 0; i < quickload_size; i++)
+ {
+ if (image.fread( &data, 1) != 1) return IMAGE_INIT_FAIL;
+
+ RAM[i+0x100] = data;
+ }
+
+ membank("bankr0")->set_entry(0);
+ membank("bank3")->set_entry(0);
+ RAM[0x80]=0; // clear out command tail
+ RAM[0x81]=0;
+ m_maincpu->set_pc(0x100); // start program
+ return IMAGE_INIT_PASS;
+}