paia/midi2cv8.cpp: Adding driver for MIDI2CV8. (#13298)

* paia/midi2cv8.cpp: Adding "not working" driver for MIDI2CV8.
Includes layout.

* midi2cv8: Marked as working.
This commit is contained in:
m1macrophage 2025-01-31 06:19:23 -08:00 committed by GitHub
parent 078322da16
commit 33a77cc643
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 682 additions and 0 deletions

View File

@ -0,0 +1,282 @@
<?xml version="1.0"?>
<!--
license:CC0-1.0
copyright-holders:m1macrophage
-->
<mamelayout version="2">
<!-- Text elements -->
<element name="text_power">
<text string="POWER" align="1"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<element name="text_system">
<text string="system" align="1"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<repeat count="8">
<param name="num" start="1" increment="1"/>
<element name="text_num_~num~">
<text string="~num~"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
</repeat>
<element name="text_on">
<text string="on"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<element name="text_reset">
<text string="reset" align="1"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<element name="text_reset_caption">
<text string="F3"><color red="0" green="0" blue="0"/></text>
</element>
<element name="text_midi">
<text string="MIDI" align="1"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<element name="text_midi_in">
<text string="In" align="1"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<element name="text_midi_thru">
<text string="Thru" align="1"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<element name="text_model">
<text string="9700fr" align="0"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<element name="text_midi2cv">
<text string="MIDI to CV" align="0"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<element name="dsw_x">
<text string="X"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
<repeat count="4">
<param name="num" start="0" increment="1"/>
<element name="dsw_c_~num~">
<text string="C~num~"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
</repeat>
<repeat count="3">
<param name="num" start="0" increment="1"/>
<element name="dsw_m_~num~">
<text string="M~num~"><color red="0.7" green="0.7" blue="0.7"/></text>
</element>
</repeat>
<repeat count="8">
<param name="num" start="1" increment="1"/>
<element name="output_number_~num~">
<text string="~num~"><color red="0.0" green="0.0" blue="0.0"/></text>
</element>
</repeat>
<!-- Shapes and other UI elements -->
<element name="white_rect">
<rect><color red="0.7" green="0.7" blue="0.7"/></rect>
</element>
<element name="black_rect">
<rect><color red="0.0" green="0.0" blue="0.0"/></rect>
</element>
<element name="blue_rect">
<rect><color red="0.0" green="0.0" blue="0.5"/></rect>
</element>
<element name="gray_circle">
<disk><color red="0.6" green="0.6" blue="0.6"/></disk>
</element>
<element name="switch" defstate="0">
<rect>
<color red="0.3" green="0.3" blue="0.3"/>
<bounds x="0.0" y="0.0" width="1.0" height="1.0"/>
</rect>
<rect state="0">
<color red="0.7" green="0.7" blue="0.7"/>
<bounds x="0.7" y="0.0" width="0.3" height="1.0"/>
</rect>
<rect state="1">
<color red="0.7" green="0.7" blue="0.7"/>
<bounds x="0.0" y="0.0" width="0.3" height="1.0"/>
</rect>
</element>
<group name="dsw">
<bounds x="0" y="0" width="15" height="45"/>
<element ref="blue_rect">
<bounds x="0" y="0" width="15" height="45"/>
</element>
<element ref="text_on">
<bounds x="10" y="0" width="5" height="4"/>
</element>
<repeat count="8">
<param name="y" start="4" increment="5"/>
<param name="switch_mask" start="0x01" lshift="1"/>
<param name="switch_num" start="1" increment="1"/>
<element ref="text_num_~switch_num~">
<bounds x="0" y="~y~" width="4" height="3"/>
</element>
<element ref="switch" inputtag="dsw" inputmask="~switch_mask~">
<bounds x="5" y="~y~" width="6" height="3"/>
</element>
</repeat>
</group>
<group name="dsw_legend">
<bounds x="0" y="0" width="9" height="41"/>
<element ref="white_rect"><bounds x="0" y="5" width="1" height="19"/></element>
<element ref="white_rect"><bounds x="0" y="26" width="1" height="13"/></element>
<element ref="dsw_c_0"><bounds x="2" y="5" width="7" height="5"/></element>
<element ref="dsw_c_1"><bounds x="2" y="10" width="7" height="5"/></element>
<element ref="dsw_c_2"><bounds x="2" y="15" width="7" height="5"/></element>
<element ref="dsw_c_3"><bounds x="2" y="20" width="7" height="5"/></element>
<element ref="dsw_m_0"><bounds x="2" y="25" width="7" height="5"/></element>
<element ref="dsw_m_1"><bounds x="2" y="30" width="7" height="5"/></element>
<element ref="dsw_m_2"><bounds x="2" y="35" width="7" height="5"/></element>
<element ref="dsw_x"><bounds x="2" y="40" width="7" height="5"/></element>
</group>
<element name="screw">
<disk>
<color red="0.4" green="0.4" blue="0.4"/>
<bounds x="0.0" y="0.0" width="1.0" height="1.0"/>
</disk>
<rect>
<color red="0.7" green="0.7" blue="0.7"/>
<bounds x="0.0" y="0.4" width="1.0" height="0.2"/>
</rect>
</element>
<element name="midi_socket">
<disk><color red="0.2" green="0.2" blue="0.2"/></disk>
</element>
<element name="output_jack">
<disk><color red="0.0" green="0.0" blue="0.0"/></disk>
</element>
<element name="power_led">
<disk><color red="0.8" green="0.0" blue="0.0"/></disk>
</element>
<element name="led" defstate="0">
<disk state="0"><color red="0.3" green="0.0" blue="0.0"/></disk>
<disk state="1"><color red="0.8" green="0.0" blue="0.0"/></disk>
</element>
<!-- Voltage display -->
<element name="period">
<text string="."><color red="0.0" green="0.2" blue="0.0"/></text>
</element>
<element name="voltage_label">
<text string="V" align="2"><color red="0.0" green="0.2" blue="0.0"/></text>
</element>
<element name="voltage_integer">
<simplecounter maxstate="99" digits="1" align="2">
<color red="0.0" green="0.2" blue="0.0"/>
</simplecounter>
</element>
<element name="voltage_fractional">
<simplecounter maxstate="999" digits="3" align="2">
<color red="0.0" green="0.2" blue="0.0"/>
</simplecounter>
</element>
<group name="voltage">
<bounds width="30" height="7"/>
<element ref="voltage_integer" name="cv_~output_num~_integer">
<bounds x="0" y="0" width="10" height="7"/>
</element>
<element ref="period">
<bounds x="10" y="0" width="5" height="7"/>
</element>
<element ref="voltage_fractional" name="cv_~output_num~_fractional">
<bounds x="12" y="0" width="15" height="7"/>
</element>
<element ref="voltage_label">
<bounds x="29" y="0" width="5" height="7"/>
</element>
</group>
<!-- Output section -->
<group name="output">
<bounds width="73" height="25"/>
<element ref="white_rect">
<bounds x="0" y="0" width="73" height="25"/>
</element>
<element ref="output_jack">
<bounds x="57" y="7" width="10" height="10"/>
</element>
<element ref="output_number_~output_num~">
<bounds x="4" y="5" width="5" height="7"/>
</element>
<group ref="voltage">
<bounds x="18" y="8" width="30" height="7"/>
</group>
</group>
<!-- View definition -->
<view name="Default Layout">
<bounds x="0" y="0" width="150" height="266"/>
<!-- Top section -->
<element ref="screw"><bounds x="30" y="7" width="10" height="10"/></element>
<element ref="screw"><bounds x="107" y="7" width="10" height="10"/></element>
<!-- Power section -->
<element ref="white_rect"><bounds x="3" y="31" width="62" height="77"/></element>
<element ref="black_rect"><bounds x="5" y="33" width="57" height="73"/></element>
<group ref="dsw"><bounds x="13" y="52" width="15" height="45"/></group>
<group ref="dsw_legend"><bounds x="28" y="51" width="9" height="40"/></group>
<element ref="screw"><bounds x="16" y="36" width="10" height="10"/></element>
<element ref="text_power"><bounds x="40" y="38" width="20" height="10"/></element>
<element ref="text_system"><bounds x="13" y="99" width="20" height="6"/></element>
<element ref="text_reset"><bounds x="42" y="99" width="19" height="6"/></element>
<element ref="power_led"><bounds x="44" y="51" width="10" height="10"/></element>
<element ref="gray_circle"><bounds x="40" y="75" width="18" height="18"/></element>
<element ref="text_reset_caption"><bounds x="45" y="80" width="8" height="8"/></element>
<!-- Midi section -->
<element ref="white_rect"><bounds x="3" y="117" width="62" height="121"/></element>
<element ref="black_rect"><bounds x="5" y="119" width="57" height="117"/></element>
<element ref="midi_socket"><bounds x="8" y="137" width="35" height="35"/></element>
<element ref="midi_socket"><bounds x="8" y="185" width="35" height="35"/></element>
<element ref="screw"><bounds x="14" y="227" width="10" height="10"/></element>
<element ref="text_midi"><bounds x="44" y="127" width="15" height="8"/></element>
<element ref="text_midi_in"><bounds x="48" y="136" width="11" height="8"/></element>
<element ref="text_midi_thru"><bounds x="44" y="179" width="15" height="8"/></element>
<element ref="led" name="midi_led"><bounds x="24" y="123" width="10" height="10"/></element>
<!-- Output section -->
<repeat count="8">
<param name="group_y" start="31" increment="26"/>
<param name="output_num" start="1" increment="1"/>
<group ref="output">
<bounds x="72" y="~group_y~" width="73" height="25"/>
</group>
</repeat>
<!-- Bottom section -->
<element ref="screw"><bounds x="30" y="245" width="10" height="10"/></element>
<element ref="screw"><bounds x="107" y="245" width="10" height="10"/></element>
<element ref="text_model"><bounds xc="75" y="242" width="26" height="10"/></element>
<element ref="text_midi2cv"><bounds xc="75" y="252" width="44" height="10"/></element>
</view>
</mamelayout>

View File

@ -35955,6 +35955,10 @@ penta // bootleg
@source:pacman/schick.cpp
schick // Microhard
@source:paia/midi2cv8.cpp
midi2cv8 // PAiA midi2cv8 (V/Oct)
midi2cv8_vhz // PAiA midi2cv8 with V/Hz daughterboard
@source:palm/palm.cpp
palmiii // Palm III
palmiiic // Palm IIIc

396
src/mame/paia/midi2cv8.cpp Normal file
View File

@ -0,0 +1,396 @@
// license:BSD-3-Clause
// copyright-holders:m1macrophage
/*
The PAiA midi2cv8 is an 8-channel MIDI-to-CV converter. It is a module for
the PAiA 9700 Series modular system, but can be used as a standalone MIDI-to-CV
converter.
Dipswitches control the MIDI channel to listen to, and the operating mode.
Depending on that mode, each of the 8 outputs produces control voltage (CV),
trigger, or gate signals in response to MIDI messages.
The firmware is running on an 80C31. It listens for MIDI messages and sets the
voltage for the 8 outputs by time-multiplexing 8 sample & hold (S&H) circuits.
Specifically, the firmware will write a value to the 8-bit DAC, and after some
delay for the DAC to settle, it will enable the S&H for one output. After some
additional delay for the S&H capacitor to (dis)charge to the target value, the
firmware will disable that S&H and move on to the next one.
The midi2cv8 comes in two configurations: Volt-per-octave (V/Oct) and
Volt-per-Hertz (V/Hz).
In the V/Oct configuration, the output of the DAC (a current) is converted to a
voltage in the range 0-10V.
The V/Hz configuration adds a daughterboard and changes some of the components.
R32 (2.7Kohm) is added, and R28 is changed from 5.6Kohm to 2.7Kohm. These change
the DAC output range to 5-10V. The daughterboard is then used to divide that by
1, 2, 4, 8 or 16 (controlled by the MCU). This is a neat trick to get
exponential voltage output for 5 octaves, while only using an 8-bit DAC.
The firmware for the two configurations is the same. P1.7 of the MCU is read at
startup to detect whether the daughterboard is installed. If it is, the firmware
will switch to V/Hz mode. See the two variants of is_volts_per_hz_r().
This driver is based on the schematics, user manual and documentation provided
by the manufacturer on their website. Both the V/Oct and V/Hz configurations are
emulated. This driver cannot replace the real device. MAME does not output
physical voltages. This is just an educational tool.
Usage:
The provided layout will display the generated CVs/triggers/gates next to the
outputs.
The default dipswitch setting for "Mode" ("Mode 8 - self tests") does not
require MIDI. Just run the driver and see voltages come to life on the screen.
The other modes require supplying a MIDI input source to MAME.
Example:
./mame -listmidi # List MIDI devices, physical or virtual (e.g. DAWs).
./mame -window midi2cv8 -midiin "{midi device}"
Keep in mind that dipswitch changes don't take effect until a restart or
reset (F3).
*/
#include "emu.h"
#include "cpu/mcs51/mcs51.h"
#include "bus/midi/midiinport.h"
#include "bus/midi/midioutport.h"
#include "video/pwm.h"
#include "paia_midi2cv8.lh"
#define LOG_DAC (1U << 1)
#define LOG_CVS (1U << 2)
#define VERBOSE (LOG_GENERAL)
//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
namespace {
constexpr const char MAINCPU_TAG[] = "80c31";
class midi2cv8_state : public driver_device
{
public:
midi2cv8_state(const machine_config &mconfig, device_type type, const char *tag) ATTR_COLD
: driver_device(mconfig, type, tag)
, m_maincpu(*this, MAINCPU_TAG)
, m_midi_pwm_led(*this, "midi_pwm_led")
, m_cv_display_integer(*this, "cv_%d_integer", 1U)
, m_cv_display_fractional(*this, "cv_%d_fractional", 1U)
, m_cv(8, -1)
{
}
void midi2cv8(machine_config &config) ATTR_COLD;
protected:
static constexpr const float DAC_V_MAX = 10;
void machine_start() override ATTR_COLD;
u8 get_dac_value() const;
void update_active_cv();
virtual bool compute_cv(float *cv) const;
virtual int is_volts_per_hz_r() const;
mcs51_cpu_device &get_maincpu() { return *m_maincpu; }
private:
void midi_rxd_w(int state);
int midi_rxd_r() const;
void dac_w(u8 data);
void output_mux_select_w(u8 data);
void program_map(address_map &map) ATTR_COLD;
void external_memory_map(address_map &map) ATTR_COLD;
required_device<mcs51_cpu_device> m_maincpu;
required_device<pwm_display_device> m_midi_pwm_led;
output_finder<8> m_cv_display_integer;
output_finder<8> m_cv_display_fractional;
bool m_inhibit_output_mux = false;
u8 m_selected_output_mux = 0;
u8 m_dac_value = 0;
u8 m_midi_rxd_bit = 1; // Initial value needs to be 1, for serial "idle".
std::vector<float> m_cv;
};
// MIDI2CV8 with the V/Hz daughterboard.
class midi2cv8_vhz_state : public midi2cv8_state
{
public:
midi2cv8_vhz_state(const machine_config &mconfig, device_type type, const char *tag) ATTR_COLD
: midi2cv8_state(mconfig, type, tag)
{
}
void midi2cv8_vhz(machine_config &config) ATTR_COLD;
protected:
void machine_start() override ATTR_COLD;
bool compute_cv(float *cv) const override;
int is_volts_per_hz_r() const override;
private:
void octave_mux_select_w(u8 data);
u8 m_selected_octave_mux = 0;
};
// The implementations of midi2cv8_state and midi2cv8_vhz_state below are
// interleaved, to better demonstrate the difference in behavior between them.
u8 midi2cv8_state::get_dac_value() const
{
return m_dac_value;
}
void midi2cv8_state::update_active_cv()
{
// Mapping from CV MUX output to the output on the panel from top to bottom.
// 0 is at the top, 7 at the bottom.
static constexpr const int OUTPUT_MAPPING[8] = {0, 4, 1, 5, 2, 6, 3, 7};
if (m_inhibit_output_mux)
return;
float cv = 0;
if (!compute_cv(&cv))
return;
const int physical_output = OUTPUT_MAPPING[m_selected_output_mux];
if (cv == m_cv[physical_output])
return;
m_cv[physical_output] = cv;
const s32 cv_millis = s32(round(1000 * cv));
m_cv_display_integer[physical_output] = cv_millis / 1000;
m_cv_display_fractional[physical_output] = cv_millis % 1000;
LOGMASKED(LOG_CVS, "CV %d - %d: %f - %d @ %f\n",
physical_output + 1, m_selected_output_mux, cv, cv_millis,
machine().time().as_double());
}
bool midi2cv8_state::compute_cv(float *cv) const
{
*cv = DAC_V_MAX * get_dac_value() / 255.0F;
return true;
}
bool midi2cv8_vhz_state::compute_cv(float *cv) const
{
// -1 means the MUX input is not connected.
static constexpr const float DIVIDE_BY[8] = {-1, 1, 2, 4, 8, 16, -1, -1};
static constexpr const float V_HALF = DAC_V_MAX / 2;
assert(m_selected_octave_mux >= 0 && m_selected_octave_mux < 8);
const float divisor = DIVIDE_BY[m_selected_octave_mux];
if (divisor <= 0)
return false;
*cv = (V_HALF + V_HALF * get_dac_value() / 255.0F) / divisor;
return true;
}
int midi2cv8_state::is_volts_per_hz_r() const
{
// P1.7 pulled up by R54, but connected to GND when the V/Hz option is not
// installed. This results in P1.7 reading as 0.
return 0;
}
int midi2cv8_vhz_state::is_volts_per_hz_r() const
{
// P1.7 pulled up by R54, and connected to R5 in the V/Hz board, when
// that board is installed. This results in P1.7 reading as 1.
return 1;
}
void midi2cv8_state::midi_rxd_w(int state)
{
m_midi_rxd_bit = state;
// MIDI IN state is inverted twice (IC6:A and IC6:C) and connected to the
// cathode of LED D2. So the LED will be on when MIDI IN is low.
m_midi_pwm_led->write_element(0, 0, state ? 0 : 1);
}
int midi2cv8_state::midi_rxd_r() const
{
return m_midi_rxd_bit;
}
void midi2cv8_state::dac_w(u8 data)
{
if (m_dac_value == data)
return;
m_dac_value = data;
update_active_cv();
LOGMASKED(LOG_DAC, "DAC value: %02x\n", m_dac_value);
}
void midi2cv8_vhz_state::octave_mux_select_w(u8 data)
{
// Octave MUX (IC4) is a 4051. X0, X6 and X7 are not connected.
// MUX INH is tied low, so it is always enabled.
// P1.5 -> OCT A.
// P1.6 -> OCT B.
// P1.7 -> OCT C.
// All signals above are inverted and level-shifted by Q1-Q3.
const u8 selection = (~data & 0xe0) >> 5; // Bits 5-7.
if (m_selected_octave_mux == selection)
return;
m_selected_octave_mux = selection;
update_active_cv();
}
void midi2cv8_state::output_mux_select_w(u8 data)
{
// MUX (IC13) is a 4051.
// P3.1 -> MUX INH
// P3.2 -> MUX B
// P3.3 -> MUX C
// P3.4 -> MUX A
// All signals above are inverted and level-shifted by Q4-Q7.
data = ~data & 0x1e;
const bool inhibit = BIT(data, 1);
const u8 selection = bitswap<3>(data, 3, 2, 4);
if (inhibit == m_inhibit_output_mux && selection == m_selected_output_mux)
return;
m_inhibit_output_mux = inhibit;
m_selected_output_mux = selection;
update_active_cv();
}
void midi2cv8_state::program_map(address_map &map)
{
// A13-A15 are not connected.
map(0x0000, 0x1fff).mirror(0xe000).rom();
}
void midi2cv8_state::external_memory_map(address_map &map)
{
// Address lines ignored on external memory writes.
map(0x0000, 0x0000).mirror(0xffff).w(FUNC(midi2cv8_state::dac_w));
}
void midi2cv8_state::machine_start()
{
m_cv_display_integer.resolve();
m_cv_display_fractional.resolve();
save_item(NAME(m_inhibit_output_mux));
save_item(NAME(m_selected_output_mux));
save_item(NAME(m_dac_value));
save_item(NAME(m_midi_rxd_bit));
save_item(NAME(m_cv));
}
void midi2cv8_vhz_state::machine_start()
{
midi2cv8_state::machine_start();
save_item(NAME(m_selected_octave_mux));
}
void midi2cv8_state::midi2cv8(machine_config &config)
{
I80C31(config, m_maincpu, 12_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &midi2cv8_state::program_map);
m_maincpu->set_addrmap(AS_IO, &midi2cv8_state::external_memory_map);
m_maincpu->port_in_cb<1>().set_ioport("dsw").mask(0x1f); // P1.0-P1.4
m_maincpu->port_in_cb<1>().append(FUNC(midi2cv8_state::is_volts_per_hz_r)).lshift(7).mask(0x80); // P1.7
m_maincpu->port_in_cb<3>().set(FUNC(midi2cv8_state::midi_rxd_r)).mask(0x01); // P3.0
m_maincpu->port_in_cb<3>().append_ioport("dsw").mask(0x20); // P3.5 <- DSW BIT 5
m_maincpu->port_in_cb<3>().append_ioport("dsw").lshift(1).mask(0x80); // P3.7 <- DSW BIT 6
m_maincpu->port_out_cb<3>().set(FUNC(midi2cv8_state::output_mux_select_w));
midi_port_device &midi_in(MIDI_PORT(config, "mdin", midiin_slot, "midiin"));
MIDI_PORT(config, "mdthru", midiout_slot, "midiout");
midi_in.rxd_handler().set(FUNC(midi2cv8_state::midi_rxd_w));
midi_in.rxd_handler().append("mdthru", FUNC(midi_port_device::write_txd));
PWM_DISPLAY(config, m_midi_pwm_led).set_size(1, 1);
m_midi_pwm_led->output_x().set_output("midi_led");
// These values make the MIDI LED in the default layout functional,
// without being too annoying.
m_midi_pwm_led->set_interpolation(0.2);
m_midi_pwm_led->set_bri_levels(0.0001);
m_midi_pwm_led->set_refresh(attotime::from_hz(30));
config.set_default_layout(layout_paia_midi2cv8);
}
void midi2cv8_vhz_state::midi2cv8_vhz(machine_config &config)
{
midi2cv8(config);
get_maincpu().port_out_cb<1>().set(FUNC(midi2cv8_vhz_state::octave_mux_select_w));
}
INPUT_PORTS_START(midi2cv8)
PORT_START("dsw")
PORT_DIPNAME(0x0f, 0x00, "MIDI Channel") PORT_DIPLOCATION("SW1:1,2,3,4")
PORT_DIPSETTING( 0x00, "1")
PORT_DIPSETTING( 0x01, "2")
PORT_DIPSETTING( 0x02, "3")
PORT_DIPSETTING( 0x03, "4")
PORT_DIPSETTING( 0x04, "5")
PORT_DIPSETTING( 0x05, "6")
PORT_DIPSETTING( 0x06, "7")
PORT_DIPSETTING( 0x07, "8")
PORT_DIPSETTING( 0x08, "9")
PORT_DIPSETTING( 0x09, "10")
PORT_DIPSETTING( 0x0a, "11")
PORT_DIPSETTING( 0x0b, "12")
PORT_DIPSETTING( 0x0c, "13")
PORT_DIPSETTING( 0x0d, "14")
PORT_DIPSETTING( 0x0e, "15")
PORT_DIPSETTING( 0x0f, "16")
PORT_DIPNAME(0x70, 0x70, "Mode") PORT_DIPLOCATION("SW1:5,6,7")
PORT_DIPSETTING( 0x00, "Mode 1 - 1 voice")
PORT_DIPSETTING( 0x10, "Mode 2 - 2 voice")
PORT_DIPSETTING( 0x20, "Mode 3 - 4 voice")
PORT_DIPSETTING( 0x30, "Mode 4 - control change")
PORT_DIPSETTING( 0x40, "Mode 5 - analog drum")
PORT_DIPSETTING( 0x50, "Mode 6 - din sync")
PORT_DIPSETTING( 0x60, "Mode 7 - [unused]")
PORT_DIPSETTING( 0x70, "Mode 8 - self-tests")
PORT_DIPNAME(0x80, 0x00, "Not Connected") PORT_DIPLOCATION("SW1:8")
PORT_DIPSETTING( 0x00, DEF_STR(On))
PORT_DIPSETTING( 0x80, DEF_STR(Off))
INPUT_PORTS_END
#define ROMS_MIDI2CV8 \
ROM_REGION(0x2000, MAINCPU_TAG, 0) \
ROM_DEFAULT_BIOS("v201") \
ROM_SYSTEM_BIOS(0, "v201", "v2.01 - December 1997") \
ROMX_LOAD("midi2cv_v2.01.ic2", 0x000000, 0x002000, CRC(bae8c045) SHA1(a5db57e53831b73903a0fb171e0444e6956febc3), ROM_BIOS(0))
ROM_START(midi2cv8)
ROMS_MIDI2CV8
ROM_END
ROM_START(midi2cv8_vhz)
ROMS_MIDI2CV8
ROM_END
} // anonymous namespace
SYST(1997, midi2cv8, 0, 0, midi2cv8, midi2cv8, midi2cv8_state, empty_init, "PAiA Electronics", "midi2cv8", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE)
SYST(1997, midi2cv8_vhz, 0, 0, midi2cv8_vhz, midi2cv8, midi2cv8_vhz_state, empty_init, "PAiA Electronics", "midi2cv8 V/Hz", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE)