mirror of
https://github.com/mamedev/mame.git
synced 2024-11-16 07:48:32 +01:00
sanyo/mbc200.cpp: Better I/O:
* Added Centronics printer port. * Hooked up most of the PPI connections. * Added some UART connections (won't work, not clocked). * Fixed sub CPU I/O mapping. * Noted missing graphics ROMs (possibly kanji font).
This commit is contained in:
parent
49f6add9a6
commit
d130995c99
2 changed files with 158 additions and 61 deletions
|
@ -48,7 +48,7 @@
|
|||
#define LOG_CONF (1U << 3)
|
||||
|
||||
//#define VERBOSE (LOG_SETUP|LOG_CONF|LOG_REGS)
|
||||
//#define LOG_OUTPUT_STREAM std::cout
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_info
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@ Machine MBC-1200 is identical but sold outside of Japan
|
|||
Floppy = 5.25"
|
||||
MBC1200 has one floppy while MBC1250 has 2. The systems are otherwise identical.
|
||||
|
||||
Keyboard communicates via RS232 to UART at E0,E1. The processor and ROM for it
|
||||
are undumped / unknown. The input codes are not ascii, so using custom code until
|
||||
the required details become available.
|
||||
Keyboard communicates serially to UART at E0,E1. The keyboard uses an undumped
|
||||
8748 microcontroller with a 12*8 key matrix. The input codes are not ASCII, so
|
||||
using custom code until the required details become available.
|
||||
|
||||
On back side:
|
||||
- keyboard DIN connector
|
||||
|
@ -30,19 +30,23 @@ Some control keys: 0x14 = Home; 0x8 = Left/BS; 0xA = Down; 0xB = Up; 0xC = Right
|
|||
GAIJI.BAS doesn't work because GAIJI.FNT is missing.
|
||||
|
||||
TODO:
|
||||
- Other connections to the various PPI's
|
||||
- Less expensive synchronisation between CPUs
|
||||
- UART connections
|
||||
- PPI 9F PA0 and PA1 are connected to jumpers
|
||||
- Any other devices?
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "bus/centronics/ctronics.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "imagedev/floppy.h"
|
||||
#include "machine/i8251.h"
|
||||
#include "machine/i8255.h"
|
||||
#include "machine/keyboard.h"
|
||||
#include "machine/output_latch.h"
|
||||
#include "machine/wd_fdc.h"
|
||||
#include "sound/spkrdev.h"
|
||||
#include "video/mc6845.h"
|
||||
|
@ -60,10 +64,10 @@ class mbc200_state : public driver_device
|
|||
public:
|
||||
mbc200_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_boot_view(*this, "boot")
|
||||
, m_palette(*this, "palette")
|
||||
, m_crtc(*this, "crtc")
|
||||
, m_ppi_m(*this, "ppi_m")
|
||||
, m_ppi_s(*this, "ppi_s")
|
||||
, m_vram(*this, "vram")
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_rom(*this, "maincpu")
|
||||
|
@ -71,6 +75,7 @@ public:
|
|||
, m_speaker(*this, "speaker")
|
||||
, m_fdc(*this, "fdc")
|
||||
, m_floppy(*this, "fdc:%u", 0)
|
||||
, m_printer(*this, "printer")
|
||||
{ }
|
||||
|
||||
void mbc200(machine_config &config) ATTR_COLD;
|
||||
|
@ -81,10 +86,15 @@ protected:
|
|||
|
||||
private:
|
||||
u8 boot_m1_r(offs_t offset);
|
||||
u8 p2_porta_r();
|
||||
void p1_portc_w(u8 data);
|
||||
void pm_porta_w(u8 data);
|
||||
u8 sub_io_r(offs_t offset);
|
||||
void sub_io_w(offs_t offset, u8 data);
|
||||
u8 ps_porta_r();
|
||||
template <unsigned Bit> void ps_porta_w(int state);
|
||||
void ps_portc_w(u8 data);
|
||||
u8 pm_porta_r();
|
||||
u8 pm_portc_r();
|
||||
void pm_portb_w(u8 data);
|
||||
void pm_portc_w(u8 data);
|
||||
u8 keyboard_r(offs_t offset);
|
||||
void kbd_put(u8 data);
|
||||
MC6845_UPDATE_ROW(update_row);
|
||||
|
@ -95,10 +105,10 @@ private:
|
|||
void sub_mem(address_map &map) ATTR_COLD;
|
||||
void sub_io(address_map &map) ATTR_COLD;
|
||||
|
||||
memory_view m_boot_view;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<mc6845_device> m_crtc;
|
||||
required_device<i8255_device> m_ppi_m;
|
||||
required_device<i8255_device> m_ppi_s;
|
||||
required_shared_ptr<u8> m_vram;
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_region_ptr<u8> m_rom;
|
||||
|
@ -106,10 +116,13 @@ private:
|
|||
required_device<speaker_sound_device> m_speaker;
|
||||
required_device<mb8876_device> m_fdc;
|
||||
required_device_array<floppy_connector, 4> m_floppy;
|
||||
required_device<centronics_device> m_printer;
|
||||
|
||||
u8 m_cpu_m_sound = 0U;
|
||||
u8 m_cpu_s_sound = 0U;
|
||||
u8 m_comm_latch = 0U;
|
||||
u8 m_pm_portc = 0xffU;
|
||||
u8 m_ps_porta = 0xffU;
|
||||
u8 m_comm_data = 0xffU;
|
||||
u8 m_term_data = 0U;
|
||||
};
|
||||
|
||||
|
@ -117,8 +130,6 @@ private:
|
|||
void mbc200_state::main_mem(address_map &map)
|
||||
{
|
||||
map(0x0000, 0xffff).ram().share(m_ram);
|
||||
map(0x0000, 0x7fff).view(m_boot_view);
|
||||
m_boot_view[0](0x0000, 0x0fff).mirror(0x7000).rom().region("maincpu", 0).unmapw();
|
||||
}
|
||||
|
||||
void mbc200_state::main_opcodes(address_map &map)
|
||||
|
@ -132,10 +143,10 @@ void mbc200_state::main_io(address_map &map)
|
|||
map.global_mask(0xff);
|
||||
|
||||
//map(0xe0, 0xe1).rw("uart1", FUNC(i8251_device::read), FUNC(i8251_device::write));
|
||||
map(0xe0, 0xe1).r(FUNC(mbc200_state::keyboard_r)).nopw();
|
||||
map(0xe0, 0xe1).mirror(0x02).r(FUNC(mbc200_state::keyboard_r)).nopw();
|
||||
map(0xe4, 0xe7).rw(m_fdc, FUNC(mb8876_device::read), FUNC(mb8876_device::write));
|
||||
map(0xe8, 0xeb).rw(m_ppi_m, FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
map(0xec, 0xed).rw("uart2", FUNC(i8251_device::read), FUNC(i8251_device::write));
|
||||
map(0xec, 0xed).mirror(0x02).rw("uart2", FUNC(i8251_device::read), FUNC(i8251_device::write));
|
||||
}
|
||||
|
||||
|
||||
|
@ -143,19 +154,20 @@ void mbc200_state::sub_mem(address_map &map)
|
|||
{
|
||||
map.unmap_value_high();
|
||||
map(0x0000, 0x1fff).rom();
|
||||
map(0x2000, 0x7fff).ram();
|
||||
map(0x2000, 0x3fff).ram();
|
||||
//map(0x4000, 0x7fff).bankr(...); missing dumps of MB83256 ROMs at 13J, 11J, 10J and 12J
|
||||
map(0x8000, 0xffff).ram().share("vram");
|
||||
}
|
||||
|
||||
void mbc200_state::sub_io(address_map &map)
|
||||
{
|
||||
// I/O decoding is sloppy:
|
||||
// A7 low selects PPI 9F (read/write)
|
||||
// A6 low selects CRTC 11D (write only)
|
||||
// A5 low selects main CPU communication (read/write)
|
||||
map.unmap_value_high();
|
||||
map.global_mask(0xff);
|
||||
|
||||
map(0x70, 0x73).rw("ppi_1", FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
map(0xb0, 0xb0).rw(m_crtc, FUNC(mc6845_device::status_r), FUNC(mc6845_device::address_w));
|
||||
map(0xb1, 0xb1).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
|
||||
map(0xd0, 0xd3).rw("ppi_2", FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
map(0x00, 0xff).rw(FUNC(mbc200_state::sub_io_r), FUNC(mbc200_state::sub_io_w));
|
||||
}
|
||||
|
||||
|
||||
|
@ -164,29 +176,96 @@ u8 mbc200_state::boot_m1_r(offs_t offset)
|
|||
{
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
m_boot_view.disable();
|
||||
m_maincpu->space(AS_PROGRAM).install_ram(0x0000, 0xffff, &m_ram[0]);
|
||||
m_maincpu->space(AS_OPCODES).install_rom(0x0000, 0xffff, &m_ram[0]);
|
||||
}
|
||||
return m_ram[0x8000 | offset];
|
||||
}
|
||||
|
||||
|
||||
void mbc200_state::p1_portc_w(u8 data)
|
||||
u8 mbc200_state::sub_io_r(offs_t offset)
|
||||
{
|
||||
m_cpu_s_sound = BIT(data, 4); // used by beep command in basic
|
||||
m_speaker->level_w(m_cpu_m_sound + m_cpu_s_sound);
|
||||
u8 result = 0xff;
|
||||
|
||||
if (!BIT(offset, 7))
|
||||
result &= m_ppi_s->read(offset & 0x03);
|
||||
|
||||
if (!BIT(offset, 5))
|
||||
result &= m_ppi_m->acka_r();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void mbc200_state::pm_porta_w(u8 data)
|
||||
void mbc200_state::sub_io_w(offs_t offset, u8 data)
|
||||
{
|
||||
machine().scheduler().synchronize(); // force resync
|
||||
m_comm_latch = data; // to slave CPU
|
||||
if (!BIT(offset, 7))
|
||||
m_ppi_s->write(offset & 0x03, data);
|
||||
|
||||
if (!BIT(offset, 6))
|
||||
{
|
||||
if (BIT(offset, 0))
|
||||
m_crtc->register_w(data);
|
||||
else
|
||||
m_crtc->address_w(data);
|
||||
}
|
||||
|
||||
if (!BIT(offset, 5))
|
||||
{
|
||||
m_comm_data = data;
|
||||
m_ppi_m->pc4_w(0);
|
||||
m_ppi_m->pc4_w(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u8 mbc200_state::ps_porta_r()
|
||||
{
|
||||
return m_ps_porta;
|
||||
}
|
||||
|
||||
template <unsigned Bit>
|
||||
void mbc200_state::ps_porta_w(int state)
|
||||
{
|
||||
if (state)
|
||||
m_ps_porta |= u8(1) << Bit;
|
||||
else
|
||||
m_ps_porta &= ~(u8(1) << Bit);
|
||||
}
|
||||
|
||||
void mbc200_state::ps_portc_w(u8 data)
|
||||
{
|
||||
// FIXME: PC0, PC1, PC2 select ROM bank
|
||||
|
||||
m_pm_portc = BIT(data, 3) ? 0xff : 0xfe;
|
||||
|
||||
m_cpu_s_sound = BIT(data, 4); // used by beep command in basic
|
||||
m_speaker->level_w(m_cpu_m_sound + m_cpu_s_sound);
|
||||
|
||||
m_printer->write_init(BIT(data, 6));
|
||||
m_printer->write_strobe(BIT(~data, 7));
|
||||
}
|
||||
|
||||
u8 mbc200_state::pm_porta_r()
|
||||
{
|
||||
// Gets whatever happens to be on the slave CPU's data bus.
|
||||
// However, we know this only happens on I/O writes with A5 low.
|
||||
return m_comm_data;
|
||||
}
|
||||
|
||||
u8 mbc200_state::pm_portc_r()
|
||||
{
|
||||
return m_pm_portc;
|
||||
}
|
||||
|
||||
// Writing to PPI port B ($E9). Being programmed for output, read operations will get the current value.
|
||||
void mbc200_state::pm_portb_w(u8 data)
|
||||
{
|
||||
// The BIOS supports up tp 4 drives, (2 internal + 2 external)
|
||||
ps_porta_w<5>(BIT(data, 0));
|
||||
|
||||
m_cpu_m_sound = BIT(data, 1); // key-click
|
||||
m_speaker->level_w(m_cpu_m_sound + m_cpu_s_sound);
|
||||
|
||||
// The BIOS supports up to 4 drives, (2 internal + 2 external)
|
||||
// E: and F: are virtual swaps of A: and B:
|
||||
u8 const drivenum = (data & 0x70) >> 4;
|
||||
floppy_image_device *floppy = nullptr;
|
||||
|
@ -200,21 +279,15 @@ void mbc200_state::pm_portb_w(u8 data)
|
|||
floppy->mon_w(0);
|
||||
floppy->ss_w(BIT(data, 7));
|
||||
}
|
||||
|
||||
m_cpu_m_sound = BIT(data, 1); // key-click
|
||||
m_speaker->level_w(m_cpu_m_sound + m_cpu_s_sound);
|
||||
}
|
||||
|
||||
|
||||
u8 mbc200_state::p2_porta_r()
|
||||
void mbc200_state::pm_portc_w(u8 data)
|
||||
{
|
||||
machine().scheduler().synchronize(); // force resync
|
||||
u8 tmp = m_comm_latch;
|
||||
m_comm_latch = 0;
|
||||
m_ppi_m->pc6_w(0); // ppi_ack
|
||||
return tmp;
|
||||
ps_porta_w<6>(BIT(data, 5)); // IBF
|
||||
ps_porta_w<7>(BIT(data, 7)); // /OBF
|
||||
}
|
||||
|
||||
|
||||
/* Input ports */
|
||||
static INPUT_PORTS_START( mbc200 )
|
||||
INPUT_PORTS_END
|
||||
|
@ -279,13 +352,16 @@ void mbc200_state::machine_start()
|
|||
{
|
||||
save_item(NAME(m_cpu_m_sound));
|
||||
save_item(NAME(m_cpu_s_sound));
|
||||
save_item(NAME(m_comm_latch));
|
||||
save_item(NAME(m_pm_portc));
|
||||
save_item(NAME(m_ps_porta));
|
||||
save_item(NAME(m_comm_data));
|
||||
save_item(NAME(m_term_data));
|
||||
}
|
||||
|
||||
void mbc200_state::machine_reset()
|
||||
{
|
||||
m_boot_view.select(0);
|
||||
m_maincpu->space(AS_PROGRAM).unmap_readwrite(0x0000, 0x7fff);
|
||||
m_maincpu->space(AS_PROGRAM).install_rom(0x0000, 0x0fff, 0x7000, &m_rom[0]);
|
||||
m_maincpu->space(AS_OPCODES).install_rom(0x0000, 0x0fff, 0x7000, &m_rom[0]);
|
||||
m_maincpu->space(AS_OPCODES).install_read_handler(0x8000, 0xffff, emu::rw_delegate(*this, FUNC(mbc200_state::boot_m1_r)));
|
||||
}
|
||||
|
@ -333,27 +409,26 @@ GFXDECODE_END
|
|||
|
||||
void mbc200_state::mbc200(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
Z80(config, m_maincpu, 8_MHz_XTAL / 2); // NEC D780C-1
|
||||
// basic machine hardware
|
||||
Z80(config, m_maincpu, 16_MHz_XTAL / 4); // NEC D780C-1
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &mbc200_state::main_mem);
|
||||
m_maincpu->set_addrmap(AS_IO, &mbc200_state::main_io);
|
||||
m_maincpu->set_addrmap(AS_OPCODES, &mbc200_state::main_opcodes);
|
||||
|
||||
z80_device &subcpu(Z80(config, "subcpu", 8_MHz_XTAL / 2)); // NEC D780C-1
|
||||
z80_device &subcpu(Z80(config, "subcpu", 16_MHz_XTAL / 4)); // NEC D780C-1
|
||||
subcpu.set_addrmap(AS_PROGRAM, &mbc200_state::sub_mem);
|
||||
subcpu.set_addrmap(AS_IO, &mbc200_state::sub_io);
|
||||
|
||||
/* video hardware */
|
||||
config.set_perfect_quantum(m_maincpu); // lazy way to keep CPUs in sync
|
||||
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(50);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
|
||||
screen.set_size(640, 400);
|
||||
screen.set_visarea(0, 640-1, 0, 400-1);
|
||||
screen.set_screen_update("crtc", FUNC(hd6845s_device::screen_update));
|
||||
screen.set_raw(16_MHz_XTAL, 816, 0, 640, 420, 0, 400);
|
||||
screen.set_screen_update(m_crtc, FUNC(hd6845s_device::screen_update));
|
||||
GFXDECODE(config, "gfxdecode", m_palette, gfx_mbc200);
|
||||
PALETTE(config, m_palette, palette_device::MONOCHROME);
|
||||
|
||||
HD6845S(config, m_crtc, 8_MHz_XTAL / 4); // HD46505SP
|
||||
HD6845S(config, m_crtc, 16_MHz_XTAL / 8); // HD46505SP
|
||||
m_crtc->set_screen("screen");
|
||||
m_crtc->set_show_border_area(false);
|
||||
m_crtc->set_char_width(8);
|
||||
|
@ -364,30 +439,52 @@ void mbc200_state::mbc200(machine_config &config)
|
|||
static const double speaker_levels[4] = { 0.0, 0.6, 1.0 };
|
||||
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
||||
m_speaker->set_levels(3, speaker_levels);
|
||||
|
||||
I8255(config, "ppi_1").out_pc_callback().set(FUNC(mbc200_state::p1_portc_w));
|
||||
I8255(config, "ppi_2").in_pa_callback().set(FUNC(mbc200_state::p2_porta_r));
|
||||
|
||||
I8255(config, m_ppi_m);
|
||||
m_ppi_m->out_pa_callback().set(FUNC(mbc200_state::pm_porta_w));
|
||||
m_ppi_m->in_pa_callback().set(FUNC(mbc200_state::pm_porta_r));
|
||||
m_ppi_m->in_pc_callback().set(FUNC(mbc200_state::pm_portc_r));
|
||||
m_ppi_m->out_pb_callback().set(FUNC(mbc200_state::pm_portb_w));
|
||||
m_ppi_m->out_pc_callback().set(FUNC(mbc200_state::pm_portc_w));
|
||||
|
||||
I8251(config, "uart1", 0); // INS8251N
|
||||
I8255(config, m_ppi_s).out_pc_callback();
|
||||
m_ppi_s->in_pa_callback().set(FUNC(mbc200_state::ps_porta_r));
|
||||
m_ppi_s->out_pb_callback().set("printdata", FUNC(output_latch_device::write));
|
||||
m_ppi_s->out_pc_callback().set(FUNC(mbc200_state::ps_portc_w));
|
||||
|
||||
I8251(config, "uart2", 0); // INS8251A
|
||||
i8251_device &uart1(I8251(config, "uart1", 0)); // INS8251N
|
||||
//uart1.txd_handler().set(...); to keyboard
|
||||
uart1.rts_handler().set("uart1", FUNC(i8251_device::write_cts));
|
||||
|
||||
i8251_device &uart2(I8251(config, "uart2", 0)); // INS8251A
|
||||
uart2.txd_handler().set("rs232c", FUNC(rs232_port_device::write_txd));
|
||||
uart2.rts_handler().set("rs232c", FUNC(rs232_port_device::write_rts));
|
||||
uart2.dtr_handler().set("rs232c", FUNC(rs232_port_device::write_dtr));
|
||||
|
||||
MB8876(config, m_fdc, 8_MHz_XTAL / 8); // guess
|
||||
|
||||
FLOPPY_CONNECTOR(config, m_floppy[0], mbc200_floppies, "qd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
|
||||
FLOPPY_CONNECTOR(config, m_floppy[1], mbc200_floppies, "qd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
|
||||
FLOPPY_CONNECTOR(config, m_floppy[2], mbc200_floppies, "qd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
|
||||
FLOPPY_CONNECTOR(config, m_floppy[3], mbc200_floppies, "qd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
|
||||
FLOPPY_CONNECTOR(config, m_floppy[2], mbc200_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
|
||||
FLOPPY_CONNECTOR(config, m_floppy[3], mbc200_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
|
||||
|
||||
/* Keyboard */
|
||||
// printer
|
||||
CENTRONICS(config, m_printer, centronics_devices, "printer");
|
||||
m_printer->set_output_latch(OUTPUT_LATCH(config, "printdata"));
|
||||
m_printer->busy_handler().set(FUNC(mbc200_state::ps_porta_w<2>)).invert();
|
||||
m_printer->perror_handler().set(FUNC(mbc200_state::ps_porta_w<3>));
|
||||
m_printer->select_handler().set(FUNC(mbc200_state::ps_porta_w<4>));
|
||||
|
||||
// RS-232C
|
||||
rs232_port_device &rs232c(RS232_PORT(config, "rs232c", default_rs232_devices, nullptr));
|
||||
rs232c.rxd_handler().set("uart2", FUNC(i8251_device::write_rxd));
|
||||
rs232c.cts_handler().set("uart2", FUNC(i8251_device::write_cts));
|
||||
rs232c.dsr_handler().set("uart2", FUNC(i8251_device::write_dsr));
|
||||
|
||||
// keyboard
|
||||
generic_keyboard_device &keyboard(GENERIC_KEYBOARD(config, "keyboard", 0));
|
||||
keyboard.set_keyboard_callback(FUNC(mbc200_state::kbd_put));
|
||||
|
||||
/* software lists */
|
||||
// software lists
|
||||
SOFTWARE_LIST(config, "flop_list").set_original("mbc200");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue