summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/ymmu50.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/ymmu50.cpp')
-rw-r--r--src/mame/drivers/ymmu50.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/mame/drivers/ymmu50.cpp b/src/mame/drivers/ymmu50.cpp
new file mode 100644
index 00000000000..2cacd47d1e5
--- /dev/null
+++ b/src/mame/drivers/ymmu50.cpp
@@ -0,0 +1,249 @@
+// 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/h83002.h"
+#include "machine/mulcd.h"
+#include "sound/swp30.h"
+#include "sound/meg.h"
+
+#include "debugger.h"
+#include "speaker.h"
+
+
+static INPUT_PORTS_START( mu50 )
+ PORT_START("P7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Effect") PORT_CODE(KEYCODE_F)
+ 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("Part +") PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Part -") PORT_CODE(KEYCODE_OPENBRACE)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Mute/Solo") PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Edit") PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Play") PORT_CODE(KEYCODE_A)
+
+ PORT_START("P8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Mode") PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Eq") PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Exit") PORT_CODE(KEYCODE_BACKSPACE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Select >") PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Select <") PORT_CODE(KEYCODE_COMMA)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Value +") PORT_CODE(KEYCODE_EQUALS)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Value -") PORT_CODE(KEYCODE_MINUS)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+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_swp30(*this, "swp30")
+ , m_lcd(*this, "lcd")
+ , m_ioport_p7(*this, "P7")
+ , m_ioport_p8(*this, "P8")
+ { }
+
+ void mu50(machine_config &config);
+
+private:
+ enum {
+ P2_LCD_RS = 0x01,
+ P2_LCD_RW = 0x02,
+ P2_LCD_ENABLE = 0x04
+ };
+
+ enum {
+ P6_LCD_RS = 0x04,
+ P6_LCD_RW = 0x02,
+ P6_LCD_ENABLE = 0x01
+ };
+
+ enum {
+ PA_LCD_RS = 0x02,
+ PA_LCD_ENABLE = 0x20,
+ PA_LCD_RW = 0x40
+ };
+
+ required_device<h83002_device> m_mu50cpu;
+ required_device<swp30_device> m_swp30;
+ required_device<mulcd_device> m_lcd;
+ required_ioport m_ioport_p7;
+ required_ioport m_ioport_p8;
+
+ u8 cur_p6, cur_pa, cur_pb;
+
+ 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 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 = 0xff;
+}
+
+void mu50_state::mu50_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom().region("mu50cpu", 0);
+ map(0x200000, 0x20ffff).ram(); // 64K work RAM
+}
+
+// Grounded adc input
+u16 mu50_state::adc_zero_r()
+{
+ return 0;
+}
+
+// Analog input right (also sent to the swp)
+u16 mu50_state::adc_ar_r()
+{
+ return 0;
+}
+
+// Analog input left (also 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;
+}
+
+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;
+}
+
+
+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::ADC_0, h8_device::ADC_0).r(FUNC(mu50_state::adc_ar_r));
+ map(h8_device::ADC_1, h8_device::ADC_1).r(FUNC(mu50_state::adc_zero_r));
+ 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).r(FUNC(mu50_state::adc_zero_r));
+ 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).r(FUNC(mu50_state::adc_zero_r));
+ 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).r(FUNC(mu50_state::adc_zero_r)); // inputmod from the gate array
+}
+
+void mu50_state::mu50(machine_config &config)
+{
+ H83002(config, m_mu50cpu, 16_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();
+
+ // In truth, swp00
+ SWP30(config, m_swp30);
+ m_swp30->add_route(0, "lspeaker", 1.0);
+ m_swp30->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<h8_sci_device>("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( 0x1800000, "swp00", ROMREGION_ERASE00 )
+ROM_END
+
+CONS( 1995, mu50, 0, 0, mu50, mu50, mu50_state, empty_init, "Yamaha", "MU50", MACHINE_NOT_WORKING )