From d130995c99027f59a639a33d2b6b8e7a612287a9 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sat, 22 Apr 2023 05:44:13 +1000 Subject: 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). --- src/devices/video/mc6845.cpp | 2 +- src/mame/sanyo/mbc200.cpp | 215 +++++++++++++++++++++++++++++++------------ 2 files changed, 157 insertions(+), 60 deletions(-) diff --git a/src/devices/video/mc6845.cpp b/src/devices/video/mc6845.cpp index 18e577b6636..233d10777ae 100644 --- a/src/devices/video/mc6845.cpp +++ b/src/devices/video/mc6845.cpp @@ -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" diff --git a/src/mame/sanyo/mbc200.cpp b/src/mame/sanyo/mbc200.cpp index bd1088492c7..79613fd2292 100644 --- a/src/mame/sanyo/mbc200.cpp +++ b/src/mame/sanyo/mbc200.cpp @@ -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 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 m_palette; required_device m_crtc; required_device m_ppi_m; + required_device m_ppi_s; required_shared_ptr m_vram; required_device m_maincpu; required_region_ptr m_rom; @@ -106,10 +116,13 @@ private: required_device m_speaker; required_device m_fdc; required_device_array m_floppy; + required_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) +{ + 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::sub_io_w(offs_t offset, u8 data) +{ + 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 +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)); } -void mbc200_state::pm_porta_w(u8 data) +u8 mbc200_state::pm_porta_r() { - machine().scheduler().synchronize(); // force resync - m_comm_latch = data; // to slave CPU + // 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); - - /* Keyboard */ + 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); + + // 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"); } -- cgit v1.2.3