Skip to content

Commit b7c998b

Browse files
committed
casio/fp1100.cpp: rewrite irq section
* makes keyboard typing more consistant
1 parent 0dea559 commit b7c998b

File tree

1 file changed

+85
-67
lines changed

1 file changed

+85
-67
lines changed

Diff for: src/mame/casio/fp1100.cpp

+85-67
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,43 @@
11
// license:BSD-3-Clause
22
// copyright-holders:Angelo Salese
3-
/***************************************************************************
3+
/**************************************************************************************************
44
5-
Casio FP-1100
5+
Casio FP-1100 (GX-205)
66
7-
Info found at various sites:
7+
TODO:
8+
- Understand how to enter Test Mode, if possible at all from available romsets
9+
(cfr. page 94 of service manual)
10+
- Memory maps and machine configuration for FP-1000 with reduced VRAM;
11+
- Unimplemented instruction PER triggered in sub CPU;
12+
- SCREEN 1 mode has heavy corrupted GFXs and runs at half speed, interlace mode?
13+
- Cassette Load is untested and probably not working, uses a complex 6 pin discrete circuitry;
14+
- Sub CPU is supposed to be in WAIT except in horizontal blanking period, WAIT is not emulated.
15+
- Keyboard not working, should trigger INTF0 on key pressed but that doesn't really work even if
16+
hooked up.
17+
- bus slots (uPD765 FDC, ROMPACK, RAMPACK)
818
9-
Casio FP-1000 and FP-1100 are "pre-PC" personal computers, with
10-
Cassette, Floppy Disk, Printer and two cartridge/expansion slots. They
11-
had 32K ROM, 64K main RAM, 80x25 text display, 320x200, 640x200, 640x400
12-
graphics display. Floppy disk is 2x 5 1/4.
19+
===================================================================================================
1320
14-
The FP-1000 had 16K videoram and monochrome only. The monitor had a
15-
switch to invert the display (swap foreground and background colours).
21+
Info found at various sites:
1622
17-
The FP-1100 had 48K videoram and 8 colours.
23+
Casio FP-1000 and FP-1100 are "pre-PC" personal computers, with
24+
Cassette, Floppy Disk, Printer and two cartridge/expansion slots. They
25+
had 32K ROM, 64K main RAM, 80x25 text display, 320x200, 640x200, 640x400
26+
graphics display. Floppy disk is 2x 5 1/4.
1827
19-
Processors: Z80 @ 4MHz, uPD7801G @ 2MHz
28+
The FP-1000 had 16K videoram and monochrome only. The monitor had a
29+
switch to invert the display (swap foreground and background colours).
2030
21-
Came with BASIC built in, and you could run CP/M 2.2 from the floppy
22-
disk.
31+
The FP-1100 had 48K videoram and 8 colours.
2332
24-
The keyboard is a separate unit. It contains a beeper.
33+
Processors: Z80 @ 4MHz, uPD7801G @ 2MHz
2534
26-
TODO:
27-
- Memory maps and machine configuration for FP-1000 with reduced VRAM.
28-
- Unimplemented instruction PER triggered (can be ignored)
29-
- Display can be interlaced or non-interlaced. Interlaced not emulated.
30-
- Cassette Load is quite complex, using 6 pins of the sub-CPU. Not
31-
done.
32-
- Sub CPU is supposed to be in WAIT except in horizontal blanking
33-
period. WAIT is not emulated in our cpu.
34-
- Keyboard not working.
35-
- FDC not done.
35+
Came with BASIC built in, and you could run CP/M 2.2 from the floppy
36+
disk.
3637
38+
The keyboard is a separate unit. It contains a beeper.
3739
38-
****************************************************************************/
40+
**************************************************************************************************/
3941

4042
#include "emu.h"
4143

@@ -114,13 +116,10 @@ class fp1100_state : public driver_device
114116
u8 portc_r();
115117
void portc_w(u8 data);
116118
void centronics_busy_w(int state);
117-
INTERRUPT_GEN_MEMBER(vblank_irq);
119+
118120
MC6845_UPDATE_ROW(crtc_update_row);
119121
TIMER_DEVICE_CALLBACK_MEMBER(kansas_w);
120122

121-
void handle_int_to_main();
122-
123-
u8 m_irq_mask = 0;
124123
u8 m_slot_num = 0;
125124
u8 m_kbd_row = 0;
126125
u8 m_col_border = 0;
@@ -129,7 +128,6 @@ class fp1100_state : public driver_device
129128
u8 m_centronics_busy = 0;
130129
u8 m_cass_data[4]{};
131130
bool m_bank_sel = false;
132-
bool m_main_irq_status = false;
133131
bool m_sub_irq_status = false;
134132
bool m_cassbit = false;
135133
bool m_cassold = false;
@@ -143,6 +141,14 @@ class fp1100_state : public driver_device
143141
u8 portb = 0;
144142
u8 portc = 0;
145143
}m_upd7801;
144+
145+
u8 m_pending_interrupts = 0;
146+
u8 m_active_interrupts = 0;
147+
u8 m_interrupt_mask = 0;
148+
149+
template<int Line> void int_w(int state);
150+
TIMER_CALLBACK_MEMBER(update_interrupts);
151+
IRQ_CALLBACK_MEMBER(restart_cb);
146152
};
147153

148154
MC6845_UPDATE_ROW( fp1100_state::crtc_update_row )
@@ -197,12 +203,20 @@ void fp1100_state::main_bank_w(u8 data)
197203
m_slot_num = (m_slot_num & 3) | ((data & 1) << 2); //??
198204
}
199205

200-
// tell sub that latch has a byte
206+
/*
207+
* x--- ---- mask for main to sub (INTF2)
208+
* ---x ---- INTS (sub to main)
209+
* ---- x--- INTD
210+
* ---- -x-- INTC
211+
* ---- --x- INTB (FDC bus slot irq)
212+
* ---- ---x INTA (FDC bus slot drq)
213+
*/
201214
void fp1100_state::irq_mask_w(u8 data)
202215
{
203-
m_irq_mask = data;
204-
handle_int_to_main();
216+
m_interrupt_mask = data;
217+
machine().scheduler().synchronize(timer_expired_delegate(FUNC(fp1100_state::update_interrupts), this));
205218

219+
// TODO: this handling doesn't seem enough
206220
if (BIT(data, 7) && !m_sub_irq_status)
207221
{
208222
m_subcpu->set_input_line(UPD7810_INTF2, ASSERT_LINE);
@@ -377,44 +391,53 @@ d6 - Centronics strobe
377391
void fp1100_state::portc_w(u8 data)
378392
{
379393
u8 const bits = data ^ m_upd7801.portc;
394+
const int main_int_state = BIT(data, 3);
395+
if (BIT(m_upd7801.portc, 3) != main_int_state)
396+
int_w<4>(main_int_state);
380397
m_upd7801.portc = data;
381398

382-
if (BIT(bits, 3))
383-
{
384-
LOG("%s: PortC:%X\n",machine().describe_context(),data);
385-
handle_int_to_main();
386-
}
387399
if (BIT(bits, 5))
388400
m_cass->change_state(BIT(data, 5) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
389401
if (BIT(bits, 6))
390402
m_centronics->write_strobe(BIT(data, 6));
391403
}
392404

393-
// HOLD_LINE used because the interrupt is set and cleared by successive instructions, too fast for the maincpu to notice
394-
void fp1100_state::handle_int_to_main()
405+
// IRQ section (main)
406+
// TODO: merge with skeleton/cdc721.cpp (reuses SN74LS148N)
407+
408+
template <int Line> void fp1100_state::int_w(int state)
395409
{
396-
// IRQ is on if bit 4 of mask AND bit 3 portC
397-
if (BIT(m_upd7801.portc, 3) && BIT(m_irq_mask, 4))
398-
{
399-
if (!m_main_irq_status)
400-
{
401-
m_maincpu->set_input_line(0, HOLD_LINE);
402-
LOG("%s: Main IRQ asserted\n",machine().describe_context());
403-
// m_main_irq_status = true;
404-
}
405-
}
410+
if (BIT(m_pending_interrupts, Line) == state)
411+
return;
412+
413+
if (state)
414+
m_pending_interrupts |= 0x01 << Line;
406415
else
416+
m_pending_interrupts &= ~(0x01 << Line);
417+
418+
machine().scheduler().synchronize(timer_expired_delegate(FUNC(fp1100_state::update_interrupts), this));
419+
}
420+
421+
TIMER_CALLBACK_MEMBER(fp1100_state::update_interrupts)
422+
{
423+
m_active_interrupts = m_pending_interrupts & m_interrupt_mask;
424+
m_maincpu->set_input_line(INPUT_LINE_IRQ0, m_active_interrupts != 0 ? ASSERT_LINE : CLEAR_LINE);
425+
}
426+
427+
IRQ_CALLBACK_MEMBER(fp1100_state::restart_cb)
428+
{
429+
u8 vector = 0xf0;
430+
// INTS > INTA > INTB > INTC > INTD priority order
431+
// INTS uses 0xf0, INTA 0xf2 and so on.
432+
u8 active = bitswap<5>(m_active_interrupts, 3, 2, 1, 0, 4);
433+
while (vector < 0xfa && !BIT(active, 0))
407434
{
408-
if (m_main_irq_status)
409-
{
410-
// m_maincpu->set_input_line(0, CLEAR_LINE);
411-
// LOG("%s: Main IRQ cleared\n",machine().describe_context());
412-
m_main_irq_status = false;
413-
}
435+
active >>= 1;
436+
vector += 0x02;
414437
}
438+
return vector;
415439
}
416440

417-
418441
static INPUT_PORTS_START( fp1100 )
419442
PORT_START("KEY.0")
420443
PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
@@ -648,15 +671,8 @@ TIMER_DEVICE_CALLBACK_MEMBER( fp1100_state::kansas_w )
648671
m_cass->output(BIT(m_cass_data[3], 1) ? -1.0 : +1.0); // 1200Hz
649672
}
650673

651-
INTERRUPT_GEN_MEMBER( fp1100_state::vblank_irq )
652-
{
653-
// if (BIT(m_irq_mask, 4))
654-
// m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xf8); // Z80
655-
}
656-
657674
void fp1100_state::machine_reset()
658675
{
659-
m_main_irq_status = false;
660676
m_sub_irq_status = false;
661677
int i;
662678
u8 slot_type;
@@ -671,7 +687,7 @@ void fp1100_state::machine_reset()
671687

672688
m_bank_sel = false; // point at rom
673689

674-
m_irq_mask = 0;
690+
m_interrupt_mask = 0;
675691
m_slot_num = 0;
676692
m_kbd_row = 0;
677693
m_col_border = 0;
@@ -680,15 +696,14 @@ void fp1100_state::machine_reset()
680696
m_upd7801.porta = 0;
681697
m_upd7801.portb = 0;
682698
m_upd7801.portc = 0;
683-
m_maincpu->set_input_line_vector(0, 0xF0);
684699
}
685700

686701
void fp1100_state::fp1100(machine_config &config)
687702
{
688703
Z80(config, m_maincpu, MAIN_CLOCK/4);
689704
m_maincpu->set_addrmap(AS_PROGRAM, &fp1100_state::main_map);
690705
m_maincpu->set_addrmap(AS_IO, &fp1100_state::io_map);
691-
m_maincpu->set_vblank_int("screen", FUNC(fp1100_state::vblank_irq));
706+
m_maincpu->set_irq_acknowledge_callback(FUNC(fp1100_state::restart_cb));
692707

693708
UPD7801(config, m_subcpu, MAIN_CLOCK/4);
694709
m_subcpu->set_addrmap(AS_PROGRAM, &fp1100_state::sub_map);
@@ -701,6 +716,9 @@ void fp1100_state::fp1100(machine_config &config)
701716

702717
GENERIC_LATCH_8(config, "main2sub");
703718
GENERIC_LATCH_8(config, "sub2main");
719+
// NOTE: Needs some sync otherwise it outright refuses to boot
720+
config.set_perfect_quantum("maincpu");
721+
config.set_perfect_quantum("sub");
704722

705723
CENTRONICS(config, m_centronics, centronics_devices, "printer");
706724
m_centronics->busy_handler().set(FUNC(fp1100_state::centronics_busy_w));

0 commit comments

Comments
 (0)