// license:BSD-3-Clause // copyright-holders:R. Belmont, Olivier Galibert /************************************************************************************* Yamaha MU-50 : 16-voice polyphonic/multitimbral General MIDI/GS/XG tone modules Preliminary driver by R. Belmont and O. Galibert **************************************************************************************/ #include "emu.h" #include "bus/midi/midiinport.h" #include "bus/midi/midioutport.h" #include "cpu/h8/h83003.h" #include "machine/mulcd.h" #include "sound/swp00.h" #include "debugger.h" #include "speaker.h" static INPUT_PORTS_START( mu50 ) PORT_START("O0") PORT_BIT(0x83, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Play") PORT_CODE(KEYCODE_A) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Edit") PORT_CODE(KEYCODE_E) PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Mute/Solo") PORT_CODE(KEYCODE_S) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Part -") PORT_CODE(KEYCODE_OPENBRACE) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Part +") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_START("O1") PORT_BIT(0x83, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Util") PORT_CODE(KEYCODE_U) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Effect") PORT_CODE(KEYCODE_F) PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Select <") PORT_CODE(KEYCODE_COMMA) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Select >") PORT_CODE(KEYCODE_STOP) PORT_START("O2") PORT_BIT(0x83, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Mode") PORT_CODE(KEYCODE_M) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Exit") PORT_CODE(KEYCODE_BACKSPACE) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Value -") PORT_CODE(KEYCODE_MINUS) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Value +") PORT_CODE(KEYCODE_EQUALS) INPUT_PORTS_END class mu50_state : public driver_device { public: mu50_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_mu50cpu(*this, "mu50cpu") , m_swp00(*this, "swp00") , m_lcd(*this, "lcd") , m_ioport_o0(*this, "O0") , m_ioport_o1(*this, "O1") , m_ioport_o2(*this, "O2") { } void mu50(machine_config &config); private: enum { P6_LCD_RS = 0x04, P6_LCD_RW = 0x02, P6_LCD_ENABLE = 0x01 }; required_device m_mu50cpu; required_device m_swp00; required_device m_lcd; required_ioport m_ioport_o0; required_ioport m_ioport_o1; required_ioport m_ioport_o2; u8 cur_p6, cur_pa, cur_pb, cur_pc; u16 adc_zero_r(); u16 adc_ar_r(); u16 adc_al_r(); u16 adc_midisw_r(); u16 adc_battery_r(); void p6_w(u16 data); u16 p6_r(); void pa_w(u16 data); u16 pa_r(); void pb_w(u16 data); u16 pb_r(); void pc_w(u16 data); u16 pc_r(); void mu50_iomap(address_map &map); void mu50_map(address_map &map); virtual void machine_start() override; }; void mu50_state::machine_start() { cur_p6 = cur_pa = cur_pb = cur_pc = 0xff; } void mu50_state::mu50_map(address_map &map) { map(0x000000, 0x07ffff).rom().region("mu50cpu", 0); map(0x200000, 0x20ffff).ram(); // 64K work RAM map(0x400000, 0x400fff).m(m_swp00, FUNC(swp00_device::map)).umask16(0xff00); } // Grounded adc input u16 mu50_state::adc_zero_r() { return 0; } // Analog input right (not sent to the swp) u16 mu50_state::adc_ar_r() { return 0; } // Analog input left (not sent to the swp) u16 mu50_state::adc_al_r() { return 0; } // Put the host switch to pure midi u16 mu50_state::adc_midisw_r() { return 0; } // Battery level u16 mu50_state::adc_battery_r() { return 0x200; } void mu50_state::p6_w(u16 data) { data ^= P6_LCD_ENABLE; if(!(cur_p6 & P6_LCD_ENABLE) && (data & P6_LCD_ENABLE)) { if(!(cur_p6 & P6_LCD_RW)) { if(cur_p6 & P6_LCD_RS) m_lcd->data_write(cur_pa); else m_lcd->control_write(cur_pa); } } cur_p6 = data; } u16 mu50_state::p6_r() { return cur_p6; } u16 mu50_state::pb_r() { return cur_pb; } void mu50_state::pb_w(u16 data) { cur_pb = data; } void mu50_state::pa_w(u16 data) { cur_pa = data; } void mu50_state::pc_w(u16 data) { cur_pc = data; } u16 mu50_state::pa_r() { if((cur_p6 & P6_LCD_ENABLE)) { if(cur_p6 & P6_LCD_RW) { if(cur_p6 & P6_LCD_RS) return m_lcd->data_read(); else return m_lcd->control_read(); } else return 0x00; } return cur_pa; } u16 mu50_state::pc_r() { u16 res = cur_pc | 0x7c; if(!(cur_pc & 0x01)) res &= m_ioport_o0->read(); if(!(cur_pc & 0x02)) res &= m_ioport_o1->read(); if(!(cur_pc & 0x80)) res &= m_ioport_o2->read(); return res; } void mu50_state::mu50_iomap(address_map &map) { map(h8_device::PORT_6, h8_device::PORT_6).rw(FUNC(mu50_state::p6_r), FUNC(mu50_state::p6_w)); map(h8_device::PORT_A, h8_device::PORT_A).rw(FUNC(mu50_state::pa_r), FUNC(mu50_state::pa_w)); map(h8_device::PORT_B, h8_device::PORT_B).rw(FUNC(mu50_state::pb_r), FUNC(mu50_state::pb_w)); map(h8_device::PORT_C, h8_device::PORT_C).rw(FUNC(mu50_state::pc_r), FUNC(mu50_state::pc_w)); map(h8_device::ADC_0, h8_device::ADC_0).r(FUNC(mu50_state::adc_ar_r)); map(h8_device::ADC_1, h8_device::ADC_1).lr16([]() -> u16 { return 0; }, "gnd"); map(h8_device::ADC_2, h8_device::ADC_2).r(FUNC(mu50_state::adc_al_r)); map(h8_device::ADC_3, h8_device::ADC_3).lr16([]() -> u16 { return 0; }, "gnd"); map(h8_device::ADC_4, h8_device::ADC_4).r(FUNC(mu50_state::adc_midisw_r)); map(h8_device::ADC_5, h8_device::ADC_6).lr16([]() -> u16 { return 0; }, "gnd"); map(h8_device::ADC_6, h8_device::ADC_6).r(FUNC(mu50_state::adc_battery_r)); map(h8_device::ADC_7, h8_device::ADC_7).lr16([]() -> u16 { return 0; }, "gnd"); } void mu50_state::mu50(machine_config &config) { H83003(config, m_mu50cpu, 12_MHz_XTAL); m_mu50cpu->set_addrmap(AS_PROGRAM, &mu50_state::mu50_map); m_mu50cpu->set_addrmap(AS_IO, &mu50_state::mu50_iomap); MULCD(config, m_lcd); SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); SWP00(config, m_swp00); m_swp00->add_route(0, "lspeaker", 1.0); m_swp00->add_route(1, "rspeaker", 1.0); auto &mdin_a(MIDI_PORT(config, "mdin_a")); midiin_slot(mdin_a); mdin_a.rxd_handler().set("mu50cpu:sci1", FUNC(h8_sci_device::rx_w)); auto &mdin_b(MIDI_PORT(config, "mdin_b")); midiin_slot(mdin_b); mdin_b.rxd_handler().set("mu50cpu:sci0", FUNC(h8_sci_device::rx_w)); auto &mdout(MIDI_PORT(config, "mdout")); midiout_slot(mdout); m_mu50cpu->subdevice("sci0")->tx_handler().set(mdout, FUNC(midi_port_device::write_txd)); } ROM_START( mu50 ) ROM_REGION( 0x80000, "mu50cpu", 0 ) ROM_LOAD16_WORD_SWAP( "yamaha_mu50.bin", 0x000000, 0x080000, CRC(507168ad) SHA1(58c41f10d292cac35ef0e8f93029fbc4685df586) ) ROM_REGION( 0x400000, "swp00", ROMREGION_ERASE00 ) ROM_LOAD( "xq057b00.ic18", 0x000000, 0x200000, NO_DUMP) ROM_LOAD( "xq058b00.ic18", 0x200000, 0x200000, NO_DUMP) ROM_END CONS( 1995, mu50, 0, 0, mu50, mu50, mu50_state, empty_init, "Yamaha", "MU50", MACHINE_NOT_WORKING )