summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/casio/fp1100.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/casio/fp1100.cpp')
-rw-r--r--src/mame/casio/fp1100.cpp152
1 files changed, 85 insertions, 67 deletions
diff --git a/src/mame/casio/fp1100.cpp b/src/mame/casio/fp1100.cpp
index c66b344dccf..db8743e4b55 100644
--- a/src/mame/casio/fp1100.cpp
+++ b/src/mame/casio/fp1100.cpp
@@ -1,41 +1,43 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
- Casio FP-1100
+Casio FP-1100 (GX-205)
- Info found at various sites:
+TODO:
+- Understand how to enter Test Mode, if possible at all from available romsets
+ (cfr. page 94 of service manual)
+- Memory maps and machine configuration for FP-1000 with reduced VRAM;
+- Unimplemented instruction PER triggered in sub CPU;
+- SCREEN 1 mode has heavy corrupted GFXs and runs at half speed, interlace mode?
+- Cassette Load is untested and probably not working, uses a complex 6 pin discrete circuitry;
+- Sub CPU is supposed to be in WAIT except in horizontal blanking period, WAIT is not emulated.
+- Keyboard not working, should trigger INTF0 on key pressed but that doesn't really work even if
+ hooked up.
+- bus slots (uPD765 FDC, ROMPACK, RAMPACK)
- Casio FP-1000 and FP-1100 are "pre-PC" personal computers, with
- Cassette, Floppy Disk, Printer and two cartridge/expansion slots. They
- had 32K ROM, 64K main RAM, 80x25 text display, 320x200, 640x200, 640x400
- graphics display. Floppy disk is 2x 5 1/4.
+===================================================================================================
- The FP-1000 had 16K videoram and monochrome only. The monitor had a
- switch to invert the display (swap foreground and background colours).
+Info found at various sites:
- The FP-1100 had 48K videoram and 8 colours.
+Casio FP-1000 and FP-1100 are "pre-PC" personal computers, with
+Cassette, Floppy Disk, Printer and two cartridge/expansion slots. They
+had 32K ROM, 64K main RAM, 80x25 text display, 320x200, 640x200, 640x400
+graphics display. Floppy disk is 2x 5 1/4.
- Processors: Z80 @ 4MHz, uPD7801G @ 2MHz
+The FP-1000 had 16K videoram and monochrome only. The monitor had a
+switch to invert the display (swap foreground and background colours).
- Came with BASIC built in, and you could run CP/M 2.2 from the floppy
- disk.
+The FP-1100 had 48K videoram and 8 colours.
- The keyboard is a separate unit. It contains a beeper.
+Processors: Z80 @ 4MHz, uPD7801G @ 2MHz
- TODO:
- - Memory maps and machine configuration for FP-1000 with reduced VRAM.
- - Unimplemented instruction PER triggered (can be ignored)
- - Display can be interlaced or non-interlaced. Interlaced not emulated.
- - Cassette Load is quite complex, using 6 pins of the sub-CPU. Not
- done.
- - Sub CPU is supposed to be in WAIT except in horizontal blanking
- period. WAIT is not emulated in our cpu.
- - Keyboard not working.
- - FDC not done.
+Came with BASIC built in, and you could run CP/M 2.2 from the floppy
+disk.
+The keyboard is a separate unit. It contains a beeper.
-****************************************************************************/
+**************************************************************************************************/
#include "emu.h"
@@ -114,13 +116,10 @@ private:
u8 portc_r();
void portc_w(u8 data);
void centronics_busy_w(int state);
- INTERRUPT_GEN_MEMBER(vblank_irq);
+
MC6845_UPDATE_ROW(crtc_update_row);
TIMER_DEVICE_CALLBACK_MEMBER(kansas_w);
- void handle_int_to_main();
-
- u8 m_irq_mask = 0;
u8 m_slot_num = 0;
u8 m_kbd_row = 0;
u8 m_col_border = 0;
@@ -129,7 +128,6 @@ private:
u8 m_centronics_busy = 0;
u8 m_cass_data[4]{};
bool m_bank_sel = false;
- bool m_main_irq_status = false;
bool m_sub_irq_status = false;
bool m_cassbit = false;
bool m_cassold = false;
@@ -143,6 +141,14 @@ private:
u8 portb = 0;
u8 portc = 0;
}m_upd7801;
+
+ u8 m_pending_interrupts = 0;
+ u8 m_active_interrupts = 0;
+ u8 m_interrupt_mask = 0;
+
+ template<int Line> void int_w(int state);
+ TIMER_CALLBACK_MEMBER(update_interrupts);
+ IRQ_CALLBACK_MEMBER(restart_cb);
};
MC6845_UPDATE_ROW( fp1100_state::crtc_update_row )
@@ -197,12 +203,20 @@ void fp1100_state::main_bank_w(u8 data)
m_slot_num = (m_slot_num & 3) | ((data & 1) << 2); //??
}
-// tell sub that latch has a byte
+/*
+ * x--- ---- mask for main to sub (INTF2)
+ * ---x ---- INTS (sub to main)
+ * ---- x--- INTD
+ * ---- -x-- INTC
+ * ---- --x- INTB (FDC bus slot irq)
+ * ---- ---x INTA (FDC bus slot drq)
+ */
void fp1100_state::irq_mask_w(u8 data)
{
- m_irq_mask = data;
- handle_int_to_main();
+ m_interrupt_mask = data;
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(fp1100_state::update_interrupts), this));
+ // TODO: this handling doesn't seem enough
if (BIT(data, 7) && !m_sub_irq_status)
{
m_subcpu->set_input_line(UPD7810_INTF2, ASSERT_LINE);
@@ -377,44 +391,53 @@ d6 - Centronics strobe
void fp1100_state::portc_w(u8 data)
{
u8 const bits = data ^ m_upd7801.portc;
+ const int main_int_state = BIT(data, 3);
+ if (BIT(m_upd7801.portc, 3) != main_int_state)
+ int_w<4>(main_int_state);
m_upd7801.portc = data;
- if (BIT(bits, 3))
- {
- LOG("%s: PortC:%X\n",machine().describe_context(),data);
- handle_int_to_main();
- }
if (BIT(bits, 5))
m_cass->change_state(BIT(data, 5) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
if (BIT(bits, 6))
m_centronics->write_strobe(BIT(data, 6));
}
-// HOLD_LINE used because the interrupt is set and cleared by successive instructions, too fast for the maincpu to notice
-void fp1100_state::handle_int_to_main()
+// IRQ section (main)
+// TODO: merge with skeleton/cdc721.cpp (reuses SN74LS148N)
+
+template <int Line> void fp1100_state::int_w(int state)
{
- // IRQ is on if bit 4 of mask AND bit 3 portC
- if (BIT(m_upd7801.portc, 3) && BIT(m_irq_mask, 4))
- {
- if (!m_main_irq_status)
- {
- m_maincpu->set_input_line(0, HOLD_LINE);
- LOG("%s: Main IRQ asserted\n",machine().describe_context());
-// m_main_irq_status = true;
- }
- }
+ if (BIT(m_pending_interrupts, Line) == state)
+ return;
+
+ if (state)
+ m_pending_interrupts |= 0x01 << Line;
else
+ m_pending_interrupts &= ~(0x01 << Line);
+
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(fp1100_state::update_interrupts), this));
+}
+
+TIMER_CALLBACK_MEMBER(fp1100_state::update_interrupts)
+{
+ m_active_interrupts = m_pending_interrupts & m_interrupt_mask;
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, m_active_interrupts != 0 ? ASSERT_LINE : CLEAR_LINE);
+}
+
+IRQ_CALLBACK_MEMBER(fp1100_state::restart_cb)
+{
+ u8 vector = 0xf0;
+ // INTS > INTA > INTB > INTC > INTD priority order
+ // INTS uses 0xf0, INTA 0xf2 and so on.
+ u8 active = bitswap<5>(m_active_interrupts, 3, 2, 1, 0, 4);
+ while (vector < 0xfa && !BIT(active, 0))
{
- if (m_main_irq_status)
- {
-// m_maincpu->set_input_line(0, CLEAR_LINE);
-// LOG("%s: Main IRQ cleared\n",machine().describe_context());
- m_main_irq_status = false;
- }
+ active >>= 1;
+ vector += 0x02;
}
+ return vector;
}
-
static INPUT_PORTS_START( fp1100 )
PORT_START("KEY.0")
PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
@@ -648,15 +671,8 @@ TIMER_DEVICE_CALLBACK_MEMBER( fp1100_state::kansas_w )
m_cass->output(BIT(m_cass_data[3], 1) ? -1.0 : +1.0); // 1200Hz
}
-INTERRUPT_GEN_MEMBER( fp1100_state::vblank_irq )
-{
-// if (BIT(m_irq_mask, 4))
-// m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xf8); // Z80
-}
-
void fp1100_state::machine_reset()
{
- m_main_irq_status = false;
m_sub_irq_status = false;
int i;
u8 slot_type;
@@ -671,7 +687,7 @@ void fp1100_state::machine_reset()
m_bank_sel = false; // point at rom
- m_irq_mask = 0;
+ m_interrupt_mask = 0;
m_slot_num = 0;
m_kbd_row = 0;
m_col_border = 0;
@@ -680,7 +696,6 @@ void fp1100_state::machine_reset()
m_upd7801.porta = 0;
m_upd7801.portb = 0;
m_upd7801.portc = 0;
- m_maincpu->set_input_line_vector(0, 0xF0);
}
void fp1100_state::fp1100(machine_config &config)
@@ -688,7 +703,7 @@ void fp1100_state::fp1100(machine_config &config)
Z80(config, m_maincpu, MAIN_CLOCK/4);
m_maincpu->set_addrmap(AS_PROGRAM, &fp1100_state::main_map);
m_maincpu->set_addrmap(AS_IO, &fp1100_state::io_map);
- m_maincpu->set_vblank_int("screen", FUNC(fp1100_state::vblank_irq));
+ m_maincpu->set_irq_acknowledge_callback(FUNC(fp1100_state::restart_cb));
UPD7801(config, m_subcpu, MAIN_CLOCK/4);
m_subcpu->set_addrmap(AS_PROGRAM, &fp1100_state::sub_map);
@@ -701,6 +716,9 @@ void fp1100_state::fp1100(machine_config &config)
GENERIC_LATCH_8(config, "main2sub");
GENERIC_LATCH_8(config, "sub2main");
+ // NOTE: Needs some sync otherwise it outright refuses to boot
+ config.set_perfect_quantum("maincpu");
+ config.set_perfect_quantum("sub");
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->busy_handler().set(FUNC(fp1100_state::centronics_busy_w));