mirror of
https://github.com/holub/mame
synced 2025-04-09 18:17:44 +03:00
Polysix: Add basic initial wave generation, "organ" eg, plus default nvram and floppy support.
This commit is contained in:
parent
b6aeaff34f
commit
68c049b67d
26
hash/polysix.xml
Normal file
26
hash/polysix.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
|
||||
<!--
|
||||
license:CC0-1.0
|
||||
-->
|
||||
<softwarelist name="polysix" description="Korg Polysix tapes">
|
||||
|
||||
<software name="presets" supported="yes">
|
||||
<description>Factory presets</description>
|
||||
<year>1981</year>
|
||||
<publisher>Korg</publisher>
|
||||
<part name="a" interface="polysix">
|
||||
<feature name="part_id" value="Bank A"/>
|
||||
<dataarea name="tape" size="42706">
|
||||
<rom name="Polysix factory sounds a 8bit 11kHz.wav" size="42706" crc="4ff23b82" sha1="d3b5b17f7aab0fe24ce05fcd4e85dfeb3fadca00"/>
|
||||
</dataarea>
|
||||
</part>
|
||||
<part name="b" interface="polysix">
|
||||
<feature name="part_id" value="Bank B"/>
|
||||
<dataarea name="tape" size="42896">
|
||||
<rom name="Polysix factory sounds b 8bit 11kHz.wav" size="42896" crc="d19be09b" sha1="587816939c558a91cb058a6e54ffb36c82a39f42"/>
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
</softwarelist>
|
@ -8,36 +8,58 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/mcs48/mcs48.h"
|
||||
#include "imagedev/cassette.h"
|
||||
#include "machine/nvram.h"
|
||||
#include "softlist_dev.h"
|
||||
#include "speaker.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class polysix_state : public driver_device
|
||||
class polysix_sound_block : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
polysix_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_progmcu(*this, "progmcu")
|
||||
, m_keymcu(*this, "keymcu")
|
||||
, m_keyboard(*this, "K%u", 0U)
|
||||
, m_progboard(*this, "P%u", 0U)
|
||||
, m_knobs(*this, "A%x", 0U)
|
||||
{
|
||||
}
|
||||
polysix_sound_block(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
virtual void machine_start() override ATTR_COLD;
|
||||
void polysix(machine_config &config);
|
||||
void set_pitch(int channel, u8 pitch);
|
||||
void set_gates(u8 gates);
|
||||
void set_effect_speed(u8 value);
|
||||
void set_cutoff(u8 value);
|
||||
void set_eg_intensity(u8 value);
|
||||
void set_resonance(u8 value);
|
||||
void set_attack(u8 value);
|
||||
void set_decay(u8 value);
|
||||
void set_suspend(u8 value);
|
||||
void set_release(u8 value);
|
||||
void set_keyboard_tracking(u8 value);
|
||||
void set_pw_pwm(u8 value);
|
||||
void set_pwm_speed(u8 value);
|
||||
void set_mg_speed(u8 value);
|
||||
void set_mg_delay(u8 value);
|
||||
void set_mg_level(u8 value);
|
||||
void set_control_low(u8 value);
|
||||
void set_control_high(u8 value);
|
||||
|
||||
u8 get_control_low();
|
||||
|
||||
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
required_device<mcs48_cpu_device> m_progmcu;
|
||||
required_device<mcs48_cpu_device> m_keymcu;
|
||||
std::unique_ptr<u8[]> m_nvram_ptr;
|
||||
required_ioport_array<10> m_keyboard;
|
||||
required_ioport_array<8> m_progboard;
|
||||
required_ioport_array<16> m_knobs;
|
||||
static const std::array<float, 0x100> phase_step;
|
||||
static const std::array<float, 0x100> pwm_phase_step;
|
||||
static const std::array<float, 0x100> pw_threshold;
|
||||
|
||||
std::array<u8, 8> m_pitch;
|
||||
sound_stream *m_stream;
|
||||
|
||||
std::array<float, 6> m_phase;
|
||||
std::array<float, 6> m_organ_eg;
|
||||
|
||||
float m_pwm_phase;
|
||||
|
||||
std::array<u8, 6> m_pitch;
|
||||
u8 m_gates;
|
||||
u8 m_current_gates;
|
||||
|
||||
u8 m_effect_speed;
|
||||
u8 m_cutoff;
|
||||
@ -54,8 +76,386 @@ private:
|
||||
u8 m_mg_delay;
|
||||
u8 m_mg_level;
|
||||
|
||||
u8 m_control_low;
|
||||
u8 m_control_high;
|
||||
};
|
||||
|
||||
DEFINE_DEVICE_TYPE(POLYSIX_SOUND_BLOCK, polysix_sound_block, "polysix_sound_block", "Korg Polysix sound block")
|
||||
|
||||
// Phase step at 48KHz for a given pitch for the main oscillator.
|
||||
// Real range is 0 (C0) to 84 (C7), since it's a 61-keys, 5 octaves
|
||||
// keyboard with +/- 1 octave transpose capability.
|
||||
|
||||
const std::array<float, 0x100> polysix_sound_block::phase_step = []() {
|
||||
std::array<float, 0x100> steps;
|
||||
// Tune A4 = 440Hz
|
||||
for(int i=0; i != 0x100; i++)
|
||||
steps[i] = 440.0 * pow(2, (i - 12*4 - 9)/12.0) / 48000;
|
||||
return steps;
|
||||
}();
|
||||
|
||||
// Phase step for the pwm. Actual curve is unclear but looks linear.
|
||||
|
||||
const std::array<float, 0x100> polysix_sound_block::pwm_phase_step = []() {
|
||||
std::array<float, 0x100> steps;
|
||||
// 0 = 0Hz, max = 20Hz, possibly linear?
|
||||
for(int i=0; i != 0x100; i++)
|
||||
steps[i] = 20 * (i/255.0) / 48000;
|
||||
return steps;
|
||||
}();
|
||||
|
||||
// Threshold for the pulse width, linear between 0.5 and 1.1, where 1
|
||||
// is the actual max value.
|
||||
|
||||
const std::array<float, 0x100> polysix_sound_block::pw_threshold = []() {
|
||||
std::array<float, 0x100> thr;
|
||||
for(int i=0; i != 0x100; i++)
|
||||
thr[i] = 0.5 + 0.6 * (i/255.0);
|
||||
return thr;
|
||||
}();
|
||||
|
||||
polysix_sound_block::polysix_sound_block(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, POLYSIX_SOUND_BLOCK, tag, owner, clock)
|
||||
, device_sound_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
void polysix_sound_block::device_start()
|
||||
{
|
||||
m_stream = stream_alloc(0, 1, 48000);
|
||||
|
||||
save_item(NAME(m_phase));
|
||||
save_item(NAME(m_organ_eg));
|
||||
save_item(NAME(m_pwm_phase));
|
||||
|
||||
save_item(NAME(m_pitch));
|
||||
save_item(NAME(m_gates));
|
||||
save_item(NAME(m_current_gates));
|
||||
save_item(NAME(m_effect_speed));
|
||||
save_item(NAME(m_cutoff));
|
||||
save_item(NAME(m_eg_intensity));
|
||||
save_item(NAME(m_resonance));
|
||||
save_item(NAME(m_attack));
|
||||
save_item(NAME(m_decay));
|
||||
save_item(NAME(m_suspend));
|
||||
save_item(NAME(m_release));
|
||||
save_item(NAME(m_keyboard_tracking));
|
||||
save_item(NAME(m_pw_pwm));
|
||||
save_item(NAME(m_pwm_speed));
|
||||
save_item(NAME(m_mg_speed));
|
||||
save_item(NAME(m_mg_delay));
|
||||
save_item(NAME(m_mg_level));
|
||||
save_item(NAME(m_control_low));
|
||||
save_item(NAME(m_control_high));
|
||||
|
||||
std::fill(m_phase.begin(), m_phase.end(), 0);
|
||||
std::fill(m_organ_eg.begin(), m_organ_eg.end(), 0);
|
||||
m_pwm_phase = 0;
|
||||
|
||||
std::fill(m_pitch.begin(), m_pitch.end(), 0);
|
||||
|
||||
m_effect_speed = 0;
|
||||
m_cutoff = 0;
|
||||
m_eg_intensity = 0;
|
||||
m_resonance = 0;
|
||||
m_attack = 0;
|
||||
m_decay = 0;
|
||||
m_suspend = 0;
|
||||
m_release = 0;
|
||||
m_keyboard_tracking = 0;
|
||||
m_pw_pwm = 0;
|
||||
m_pwm_speed = 0;
|
||||
m_mg_speed = 0;
|
||||
m_mg_delay = 0;
|
||||
m_mg_level = 0;
|
||||
m_control_low = 0;
|
||||
m_control_high = 0;
|
||||
m_gates = 0;
|
||||
m_current_gates = 0;
|
||||
}
|
||||
|
||||
void polysix_sound_block::device_reset()
|
||||
{
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_pitch(int channel, u8 pitch)
|
||||
{
|
||||
if(m_pitch[channel] != pitch) {
|
||||
m_stream->update();
|
||||
m_pitch[channel] = pitch;
|
||||
|
||||
static const char *const notes[12] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
|
||||
logerror("channel %d pitch %02x %s%d\n", channel, pitch, notes[pitch % 12], (pitch/12));
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_gates(u8 gates)
|
||||
{
|
||||
if(gates != m_gates) {
|
||||
m_stream->update();
|
||||
m_gates = gates;
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_effect_speed(u8 value)
|
||||
{
|
||||
if(value != m_effect_speed) {
|
||||
m_stream->update();
|
||||
m_effect_speed = value;
|
||||
logerror("effect_speed = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_cutoff(u8 value)
|
||||
{
|
||||
if(value != m_cutoff) {
|
||||
m_stream->update();
|
||||
m_cutoff = value;
|
||||
logerror("cutoff = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_eg_intensity(u8 value)
|
||||
{
|
||||
if(value != m_eg_intensity) {
|
||||
m_stream->update();
|
||||
m_eg_intensity = value;
|
||||
logerror("eg_intensity = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_resonance(u8 value)
|
||||
{
|
||||
if(value != m_resonance) {
|
||||
m_stream->update();
|
||||
m_resonance = value;
|
||||
logerror("resonance = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_attack(u8 value)
|
||||
{
|
||||
if(value != m_attack) {
|
||||
m_stream->update();
|
||||
m_attack = value;
|
||||
logerror("attack = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_decay(u8 value)
|
||||
{
|
||||
if(value != m_decay) {
|
||||
m_stream->update();
|
||||
m_decay = value;
|
||||
logerror("decay = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_suspend(u8 value)
|
||||
{
|
||||
if(value != m_suspend) {
|
||||
m_stream->update();
|
||||
m_suspend = value;
|
||||
logerror("suspend = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_release(u8 value)
|
||||
{
|
||||
if(value != m_release) {
|
||||
m_stream->update();
|
||||
m_release = value;
|
||||
logerror("release = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_keyboard_tracking(u8 value)
|
||||
{
|
||||
if(value != m_keyboard_tracking) {
|
||||
m_stream->update();
|
||||
m_keyboard_tracking = value;
|
||||
logerror("keyboard_tracking = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_pw_pwm(u8 value)
|
||||
{
|
||||
if(value != m_pw_pwm) {
|
||||
m_stream->update();
|
||||
m_pw_pwm = value;
|
||||
logerror("pw_pwm = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_pwm_speed(u8 value)
|
||||
{
|
||||
if(value != m_pwm_speed) {
|
||||
m_stream->update();
|
||||
m_pwm_speed = value;
|
||||
logerror("pwm_speed = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_mg_speed(u8 value)
|
||||
{
|
||||
if(value != m_mg_speed) {
|
||||
m_stream->update();
|
||||
m_mg_speed = value;
|
||||
logerror("mg_speed = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_mg_delay(u8 value)
|
||||
{
|
||||
if(value != m_mg_delay) {
|
||||
m_stream->update();
|
||||
m_mg_delay = value;
|
||||
logerror("mg_delay = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_mg_level(u8 value)
|
||||
{
|
||||
if(value != m_mg_level) {
|
||||
m_stream->update();
|
||||
m_mg_level = value;
|
||||
logerror("mg_level = %02x\n", value);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_control_low(u8 value)
|
||||
{
|
||||
if(value != m_control_low) {
|
||||
m_stream->update();
|
||||
m_control_low = value;
|
||||
logerror("control low vco=%s wave=%s sub=%s mod=%s\n",
|
||||
BIT(value, 0, 2) == 0 ? "16'" : BIT(value, 0, 2) == 1 ? "8'" : BIT(value, 0, 2) == 2 ? "4'" : "?",
|
||||
BIT(value, 2, 2) == 1 ? "tri" : BIT(value, 2, 2) == 0 ? "pw" : BIT(value, 2, 2) == 2 ? "pwm" : "?",
|
||||
BIT(value, 4, 2) == 0 ? "off" : BIT(value, 4, 2) == 1 ? "1oct" : BIT(value, 4, 2) == 2 ? "2oct" : "?",
|
||||
BIT(value, 6, 2) == 0 ? "vca" : BIT(value, 6, 2) == 1 ? "vcf" : BIT(value, 6, 2) == 2 ? "vco" : "?"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void polysix_sound_block::set_control_high(u8 value)
|
||||
{
|
||||
if(value != m_control_high) {
|
||||
m_stream->update();
|
||||
m_control_high = value;
|
||||
logerror("control high vca-mode=%s chorus=%s phase=%s ens=%s p.vol=%x\n",
|
||||
BIT(value, 0) ? "eg" : "square",
|
||||
BIT(value, 1) ? "on" : "off",
|
||||
BIT(value, 2) ? "on" : "off",
|
||||
BIT(value, 3) ? "on" : "off",
|
||||
BIT(value, 4, 4)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
u8 polysix_sound_block::get_control_low()
|
||||
{
|
||||
return m_control_low;
|
||||
}
|
||||
|
||||
// #*#*#*#*#*#*#*#
|
||||
void polysix_sound_block::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
|
||||
{
|
||||
for(int sample=0; sample != outputs[0].samples(); sample++) {
|
||||
// u8 trigger = m_gates & ~m_current_gates;
|
||||
float out = 0;
|
||||
|
||||
// Step the pwm phase (common to all channels)
|
||||
m_pwm_phase += pwm_phase_step[m_pwm_speed];
|
||||
while(m_pwm_phase >= 2)
|
||||
m_pwm_phase -= 2;
|
||||
|
||||
// Wrap into a triangle
|
||||
float pwm_phase = m_pwm_phase >= 1 ? 2 - m_pwm_phase : m_pwm_phase;
|
||||
|
||||
// Compute the threshold
|
||||
float pw_thr = pw_threshold[m_pw_pwm];
|
||||
if(BIT(m_control_low, 3) || 1)
|
||||
// PWM mode, the modulation multiplies the threshold part over 0.5 with the phase wrapped between 0.2 and 1
|
||||
pw_thr = 0.5 + (pw_thr - 0.5) * (0.2 + pwm_phase * 0.8);
|
||||
|
||||
for(int channel = 0; channel != 6; channel ++) {
|
||||
if((m_gates ^ m_current_gates) & (1 << channel))
|
||||
logerror("channel %d %s\n", channel, (m_gates & (1<<channel)) ? "keyon" : "keyoff");
|
||||
|
||||
// Step the phase
|
||||
m_phase[channel] += phase_step[m_pitch[channel]];
|
||||
while(m_phase[channel] >= 4)
|
||||
m_phase[channel] -= 4;
|
||||
|
||||
int subosc_step = int(m_phase[channel]);
|
||||
float phase = m_phase[channel] - subosc_step;
|
||||
|
||||
// Generate the initial wave in the [-1, 1] range
|
||||
float wave;
|
||||
if(BIT(m_control_low, 2))
|
||||
// triangle
|
||||
wave = 2*(phase - 0.5);
|
||||
|
||||
else
|
||||
// PW(M)
|
||||
wave = phase >= pw_thr ? 1 : -1;
|
||||
|
||||
// Add the sub-oscillator, if active
|
||||
if(BIT(m_control_low, 4, 2))
|
||||
wave += (subosc_step & (BIT(m_control_low, 5, 1) ? 2 : 1)) ? 1 : 0;
|
||||
|
||||
// Step the organ EG
|
||||
if(BIT(m_gates, channel))
|
||||
// When gate is on, charge a 0.047uF cap through a 10K resistor
|
||||
m_organ_eg[channel] += (1-m_organ_eg[channel])*0.0433581893516088; // 1-exp(-1/(10e3 * 0.047e-6 * 48000))
|
||||
else
|
||||
// When gate is off, discharge a 0.047uF cap through a 230K resistor
|
||||
m_organ_eg[channel] -= m_organ_eg[channel]*0.00192537196422815; // 1-exp(-1/(230e3 * 0.047e-6 * 48000))
|
||||
|
||||
out += wave * m_organ_eg[channel];
|
||||
}
|
||||
|
||||
m_current_gates = m_gates;
|
||||
outputs[0].put_clamp(sample, out/2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class polysix_state : public driver_device
|
||||
{
|
||||
public:
|
||||
polysix_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_progmcu(*this, "progmcu")
|
||||
, m_keymcu(*this, "keymcu")
|
||||
, m_sound(*this, "soundblock")
|
||||
, m_keyboard(*this, "K%u", 0U)
|
||||
, m_progboard(*this, "P%u", 0U)
|
||||
, m_knobs(*this, "A%x", 0U)
|
||||
, m_tape_enable(*this, "TAPE")
|
||||
, m_tape(*this, "tape")
|
||||
{
|
||||
}
|
||||
|
||||
virtual void machine_start() override ATTR_COLD;
|
||||
void polysix(machine_config &config);
|
||||
|
||||
INPUT_CHANGED_MEMBER(tape_enable_w);
|
||||
|
||||
private:
|
||||
required_device<mcs48_cpu_device> m_progmcu;
|
||||
required_device<mcs48_cpu_device> m_keymcu;
|
||||
required_device<polysix_sound_block> m_sound;
|
||||
std::unique_ptr<u8[]> m_nvram_ptr;
|
||||
required_ioport_array<10> m_keyboard;
|
||||
required_ioport_array<8> m_progboard;
|
||||
required_ioport_array<16> m_knobs;
|
||||
required_ioport m_tape_enable;
|
||||
required_device<cassette_image_device> m_tape;
|
||||
|
||||
u16 m_pleds;
|
||||
u16 m_pctrl;
|
||||
u8 m_kleds;
|
||||
|
||||
u8 m_prog_bus;
|
||||
@ -63,10 +463,11 @@ private:
|
||||
u8 m_prog_p2;
|
||||
u8 m_key_bus;
|
||||
u8 m_keyon;
|
||||
u8 m_key_ic2;
|
||||
u8 m_key_p2;
|
||||
u8 m_trigger;
|
||||
|
||||
bool m_tape_enabled;
|
||||
|
||||
void key_bus_w(u8 data);
|
||||
u8 key_p1_r();
|
||||
void key_p2_w(u8 data);
|
||||
@ -96,67 +497,34 @@ void polysix_state::machine_start()
|
||||
subdevice<nvram_device>("nvram")->set_base(&m_nvram_ptr[0], 0x400);
|
||||
|
||||
save_pointer(NAME(m_nvram_ptr), 0x400);
|
||||
save_item(NAME(m_pitch));
|
||||
save_item(NAME(m_pleds));
|
||||
save_item(NAME(m_pctrl));
|
||||
save_item(NAME(m_kleds));
|
||||
save_item(NAME(m_key_bus));
|
||||
save_item(NAME(m_keyon));
|
||||
save_item(NAME(m_key_ic2));
|
||||
save_item(NAME(m_trigger));
|
||||
save_item(NAME(m_prog_bus));
|
||||
save_item(NAME(m_prog_p1));
|
||||
save_item(NAME(m_prog_p2));
|
||||
|
||||
save_item(NAME(m_effect_speed));
|
||||
save_item(NAME(m_cutoff));
|
||||
save_item(NAME(m_eg_intensity));
|
||||
save_item(NAME(m_resonance));
|
||||
save_item(NAME(m_attack));
|
||||
save_item(NAME(m_decay));
|
||||
save_item(NAME(m_suspend));
|
||||
save_item(NAME(m_release));
|
||||
save_item(NAME(m_keyboard_tracking));
|
||||
save_item(NAME(m_pw_pwm));
|
||||
save_item(NAME(m_pwm_speed));
|
||||
save_item(NAME(m_mg_speed));
|
||||
save_item(NAME(m_mg_delay));
|
||||
save_item(NAME(m_mg_level));
|
||||
|
||||
std::fill(m_pitch.begin(), m_pitch.end(), 0);
|
||||
|
||||
m_effect_speed = 0;
|
||||
m_cutoff = 0;
|
||||
m_eg_intensity = 0;
|
||||
m_resonance = 0;
|
||||
m_attack = 0;
|
||||
m_decay = 0;
|
||||
m_suspend = 0;
|
||||
m_release = 0;
|
||||
m_keyboard_tracking = 0;
|
||||
m_pw_pwm = 0;
|
||||
m_pwm_speed = 0;
|
||||
m_mg_speed = 0;
|
||||
m_mg_delay = 0;
|
||||
m_mg_level = 0;
|
||||
save_item(NAME(m_tape_enabled));
|
||||
|
||||
m_pleds = 0;
|
||||
m_key_bus = 0;
|
||||
m_keyon = 0;
|
||||
m_key_ic2 = 0;
|
||||
m_key_p2 = 0;
|
||||
m_trigger = 0;
|
||||
|
||||
m_prog_bus = 0;
|
||||
m_prog_p1 = 0;
|
||||
m_prog_p2 = 0;
|
||||
|
||||
m_tape_enabled = false;
|
||||
}
|
||||
|
||||
u8 polysix_state::prog_r(offs_t offset)
|
||||
{
|
||||
if(BIT(m_prog_p1, 7)) {
|
||||
u16 adr = BIT(m_prog_p2, 0) | (offset << 1) | ( BIT(m_prog_p2, 1) << 9);
|
||||
logerror("nvram_r %03x = %x\n", adr, m_nvram_ptr[adr]);
|
||||
return m_nvram_ptr[adr] | 0xf0;
|
||||
}
|
||||
|
||||
@ -167,7 +535,6 @@ void polysix_state::prog_w(offs_t offset, u8 data)
|
||||
{
|
||||
if(BIT(m_prog_p1, 7)) {
|
||||
u16 adr = BIT(m_prog_p2, 0) | (offset << 1) | ( BIT(m_prog_p2, 1) << 9);
|
||||
logerror("nvram_w %03x = %x\n", adr, data & 0x0f);
|
||||
m_nvram_ptr[adr] = data & 0x0f;
|
||||
}
|
||||
}
|
||||
@ -191,37 +558,20 @@ void polysix_state::prog_p1_w(u8 data)
|
||||
|
||||
if(BIT(chg, 6) && BIT(m_prog_p1, 6)) {
|
||||
switch(m_prog_p2 & 0xf) {
|
||||
case 0x0: if(m_prog_bus != m_effect_speed) logerror("effect_speed = %02x\n", m_prog_bus); break;
|
||||
case 0x1: if(m_prog_bus != m_cutoff) logerror("cutoff = %02x\n", m_prog_bus); break;
|
||||
case 0x2: if(m_prog_bus != m_eg_intensity) logerror("eg_intensity = %02x\n", m_prog_bus); break;
|
||||
case 0x3: if(m_prog_bus != m_resonance) logerror("resonance = %02x\n", m_prog_bus); break;
|
||||
case 0x4: if(m_prog_bus != m_attack) logerror("attack = %02x\n", m_prog_bus); break;
|
||||
case 0x5: if(m_prog_bus != m_decay) logerror("decay = %02x\n", m_prog_bus); break;
|
||||
case 0x6: if(m_prog_bus != m_suspend) logerror("suspend = %02x\n", m_prog_bus); break;
|
||||
case 0x7: if(m_prog_bus != m_release) logerror("release = %02x\n", m_prog_bus); break;
|
||||
case 0x8: if(m_prog_bus != m_keyboard_tracking) logerror("keyboard_tracking = %02x\n", m_prog_bus); break;
|
||||
case 0x9: if(m_prog_bus != m_pw_pwm) logerror("pw_pwm = %02x\n", m_prog_bus); break;
|
||||
case 0xa: if(m_prog_bus != m_pwm_speed) logerror("pwm_speed = %02x\n", m_prog_bus); break;
|
||||
case 0xb: if(m_prog_bus != m_mg_speed) logerror("mg_speed = %02x\n", m_prog_bus); break;
|
||||
case 0xc: if(m_prog_bus != m_mg_delay) logerror("mg_delay = %02x\n", m_prog_bus); break;
|
||||
case 0xd: if(m_prog_bus != m_mg_level) logerror("mg_level = %02x\n", m_prog_bus); break;
|
||||
}
|
||||
|
||||
switch(m_prog_p2 & 0xf) {
|
||||
case 0x0: m_effect_speed = m_prog_bus; break;
|
||||
case 0x1: m_cutoff = m_prog_bus; break;
|
||||
case 0x2: m_eg_intensity = m_prog_bus; break;
|
||||
case 0x3: m_resonance = m_prog_bus; break;
|
||||
case 0x4: m_attack = m_prog_bus; break;
|
||||
case 0x5: m_decay = m_prog_bus; break;
|
||||
case 0x6: m_suspend = m_prog_bus; break;
|
||||
case 0x7: m_release = m_prog_bus; break;
|
||||
case 0x8: m_keyboard_tracking = m_prog_bus; break;
|
||||
case 0x9: m_pw_pwm = m_prog_bus; break;
|
||||
case 0xa: m_pwm_speed = m_prog_bus; break;
|
||||
case 0xb: m_mg_speed = m_prog_bus; break;
|
||||
case 0xc: m_mg_delay = m_prog_bus; break;
|
||||
case 0xd: m_mg_level = m_prog_bus; break;
|
||||
case 0x0: m_sound->set_effect_speed(m_prog_bus); break;
|
||||
case 0x1: m_sound->set_cutoff(m_prog_bus); break;
|
||||
case 0x2: m_sound->set_eg_intensity(m_prog_bus); break;
|
||||
case 0x3: m_sound->set_resonance(m_prog_bus); break;
|
||||
case 0x4: m_sound->set_attack(m_prog_bus); break;
|
||||
case 0x5: m_sound->set_decay(m_prog_bus); break;
|
||||
case 0x6: m_sound->set_suspend(m_prog_bus); break;
|
||||
case 0x7: m_sound->set_release(m_prog_bus); break;
|
||||
case 0x8: m_sound->set_keyboard_tracking(m_prog_bus); break;
|
||||
case 0x9: m_sound->set_pw_pwm(m_prog_bus); break;
|
||||
case 0xa: m_sound->set_pwm_speed(m_prog_bus); break;
|
||||
case 0xb: m_sound->set_mg_speed(m_prog_bus); break;
|
||||
case 0xc: m_sound->set_mg_delay(m_prog_bus); break;
|
||||
case 0xd: m_sound->set_mg_level(m_prog_bus); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -232,10 +582,10 @@ void polysix_state::prog_p2_w(u8 data)
|
||||
m_prog_p2 = data;
|
||||
|
||||
if(BIT(chg, 4) && !BIT(m_prog_p2, 4))
|
||||
m_pctrl = (m_pctrl & 0xff00) | m_prog_bus;
|
||||
m_sound->set_control_low(m_prog_bus);
|
||||
|
||||
if(BIT(chg, 5) && !BIT(m_prog_p2, 5))
|
||||
m_pctrl = (m_pctrl & 0x00ff) | (m_prog_bus << 8);
|
||||
m_sound->set_control_high(m_prog_bus);
|
||||
|
||||
u16 old_leds = m_pleds;
|
||||
|
||||
@ -259,8 +609,8 @@ void polysix_state::prog_p2_w(u8 data)
|
||||
BIT(m_pleds, 9) ? 'B' : '.',
|
||||
BIT(m_pleds, 10) ? 'C' : '.',
|
||||
BIT(m_pleds, 11) ? 'D' : '.',
|
||||
BIT(m_pleds, 12) ? " manual" : "",
|
||||
BIT(m_pleds, 13) ? " write" : "");
|
||||
BIT(m_pleds, 12) ? " manual/found" : "",
|
||||
BIT(m_pleds, 13) ? " write/loading" : "");
|
||||
}
|
||||
|
||||
void polysix_state::prog_bus_w(u8 data)
|
||||
@ -275,8 +625,8 @@ int polysix_state::prog_t0_r()
|
||||
|
||||
int polysix_state::prog_t1_r()
|
||||
{
|
||||
logerror("prog t1\n");
|
||||
return 1;
|
||||
// logerror("prog t1 %f\n", m_tape->input());
|
||||
return m_tape->input() >= 0;
|
||||
}
|
||||
|
||||
u8 polysix_state::key_p1_r()
|
||||
@ -298,7 +648,7 @@ void polysix_state::key_bus_w(u8 data)
|
||||
}
|
||||
|
||||
// cn12 at klm-371
|
||||
// cn12-17 -> int, aoki, arpeggiator
|
||||
// cn12-17 -> int, acki, arpeggiator
|
||||
// cn12-16 = p27, gnd?
|
||||
// klm-367
|
||||
// cn05-1 = reset
|
||||
@ -312,20 +662,8 @@ void polysix_state::key_p2_w(u8 data)
|
||||
m_key_p2 = data;
|
||||
|
||||
if(BIT(chg, 3) && !BIT(m_key_p2, 3)) {
|
||||
u8 chgk = m_keyon ^ m_key_bus;
|
||||
m_keyon = m_key_bus;
|
||||
m_trigger |= m_keyon & chgk & 0x3f;
|
||||
if(m_trigger)
|
||||
logerror("keyon %c%c%c%c%c%c\n",
|
||||
BIT(m_trigger, 0) ? '0' : '.',
|
||||
BIT(m_trigger, 1) ? '1' : '.',
|
||||
BIT(m_trigger, 2) ? '2' : '.',
|
||||
BIT(m_trigger, 3) ? '3' : '.',
|
||||
BIT(m_trigger, 4) ? '4' : '.',
|
||||
BIT(m_trigger, 5) ? '5' : '.');
|
||||
m_trigger = 0;
|
||||
if(BIT(chgk, 7))
|
||||
logerror("ic45 = %02x %s\n", m_keyon, machine().describe_context());
|
||||
m_sound->set_gates(m_tape_enabled ? 0 : m_key_bus & 0x3f);
|
||||
// TODO logerror("ic45 = %02x %s\n", m_key_bus, machine().describe_context());
|
||||
}
|
||||
|
||||
if(BIT(chg, 4) && !BIT(m_key_p2, 4)) {
|
||||
@ -342,13 +680,10 @@ void polysix_state::key_p2_w(u8 data)
|
||||
|
||||
if(!BIT(m_key_p2, 5)) {
|
||||
int index = BIT(data, 0, 3);
|
||||
if(m_key_bus != m_pitch[index]) {
|
||||
m_pitch[index] = m_key_bus;
|
||||
if(index < 6)
|
||||
logerror("voice %d pitch %3d\n", index, m_key_bus);
|
||||
else
|
||||
logerror("key analog #%d = %3d\n", index, m_key_bus);
|
||||
}
|
||||
if(index < 6)
|
||||
m_sound->set_pitch(index, m_key_bus);
|
||||
else
|
||||
; // TODO
|
||||
}
|
||||
|
||||
if(BIT(chg, 7))
|
||||
@ -359,12 +694,21 @@ void polysix_state::key_p2_w(u8 data)
|
||||
|
||||
int polysix_state::key_t0_r()
|
||||
{
|
||||
return BIT(m_pctrl, 0);
|
||||
return !BIT(m_sound->get_control_low(), 0);
|
||||
}
|
||||
|
||||
int polysix_state::key_t1_r()
|
||||
{
|
||||
return BIT(m_pctrl, 01);
|
||||
return !BIT(m_sound->get_control_low(), 01);
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(polysix_state::tape_enable_w)
|
||||
{
|
||||
logerror("leds tape enable %s\n", newval ? "on" : "off");
|
||||
m_tape_enabled = newval;
|
||||
m_progmcu->set_input_line(0, newval);
|
||||
if(newval)
|
||||
m_keyon = 0;
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START(polysix)
|
||||
@ -469,21 +813,21 @@ static INPUT_PORTS_START(polysix)
|
||||
PORT_CONFSETTING( 0xc0, "1 octave")
|
||||
|
||||
PORT_START("P0")
|
||||
PORT_CONFNAME(0x03, 0x03, "VCO octave")
|
||||
PORT_CONFSETTING( 0x01, "16'")
|
||||
PORT_CONFNAME(0x03, 0x02, "VCO octave")
|
||||
PORT_CONFSETTING( 0x03, "16'")
|
||||
PORT_CONFSETTING( 0x02, "8'")
|
||||
PORT_CONFSETTING( 0x03, "4'")
|
||||
PORT_CONFNAME(0x0c, 0x0c, "Waveform")
|
||||
PORT_CONFSETTING( 0x04, "Triangle")
|
||||
PORT_CONFSETTING( 0x08, "PW")
|
||||
PORT_CONFSETTING( 0x0c, "PWM")
|
||||
PORT_CONFSETTING( 0x01, "4'")
|
||||
PORT_CONFNAME(0x0c, 0x08, "Waveform")
|
||||
PORT_CONFSETTING( 0x08, "Triangle")
|
||||
PORT_CONFSETTING( 0x0c, "PW")
|
||||
PORT_CONFSETTING( 0x04, "PWM")
|
||||
PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("P1")
|
||||
PORT_CONFNAME(0x03, 0x0c, "Sub oscillator")
|
||||
PORT_CONFSETTING( 0x01, "off")
|
||||
PORT_CONFNAME(0x03, 0x01, "Sub oscillator")
|
||||
PORT_CONFSETTING( 0x03, "off")
|
||||
PORT_CONFSETTING( 0x02, "1 oct")
|
||||
PORT_CONFSETTING( 0x03, "2 oct")
|
||||
PORT_CONFSETTING( 0x01, "2 oct")
|
||||
PORT_CONFNAME(0x0c, 0x0c, "MG modulation")
|
||||
PORT_CONFSETTING( 0x04, "VCO")
|
||||
PORT_CONFSETTING( 0x08, "VCF")
|
||||
@ -540,7 +884,9 @@ static INPUT_PORTS_START(polysix)
|
||||
PORT_START("P7")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("found / manual")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("write / loading")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("write enable")
|
||||
PORT_CONFNAME(0x04, 0x04, "write enable")
|
||||
PORT_CONFSETTING( 0x00, "enabled")
|
||||
PORT_CONFSETTING( 0x04, "disabled")
|
||||
PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("A0")
|
||||
@ -590,6 +936,12 @@ static INPUT_PORTS_START(polysix)
|
||||
|
||||
PORT_START("Af")
|
||||
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
|
||||
PORT_START("TAPE")
|
||||
PORT_CONFNAME(0x01, 0x00, "Tape access") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(polysix_state::tape_enable_w), 0)
|
||||
PORT_CONFSETTING( 0x01, "enabled")
|
||||
PORT_CONFSETTING( 0x00, "disabled")
|
||||
|
||||
INPUT_PORTS_END
|
||||
|
||||
void polysix_state::polysix(machine_config &config)
|
||||
@ -611,6 +963,17 @@ void polysix_state::polysix(machine_config &config)
|
||||
m_keymcu->t1_in_cb().set(FUNC(polysix_state::key_t1_r));
|
||||
|
||||
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // TC5514APL-3 + battery
|
||||
|
||||
CASSETTE(config, m_tape);
|
||||
m_tape->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_MUTED);
|
||||
m_tape->set_interface("polysix");
|
||||
|
||||
SOFTWARE_LIST(config, "polysix").set_original("polysix");
|
||||
|
||||
POLYSIX_SOUND_BLOCK(config, m_sound);
|
||||
m_sound->add_route(0, "speaker", 1.0);
|
||||
|
||||
SPEAKER(config, "speaker").front_center();
|
||||
}
|
||||
|
||||
ROM_START(polysix)
|
||||
@ -619,9 +982,10 @@ ROM_START(polysix)
|
||||
|
||||
ROM_REGION(0x800, "keymcu", 0)
|
||||
ROM_LOAD("d8049c-217.bin", 0x000, 0x800, CRC(246d7767) SHA1(5b608c750e7fe7832070a53a74df416fd132ecb7))
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
ROM_REGION(0x400, "nvram", 0)
|
||||
ROM_LOAD("nvram.bin", 0x000, 0x400, CRC(1a913972) SHA1(891c7c2aa2f3cd54e3dd6847fad58ab831838c3e))
|
||||
ROM_END
|
||||
|
||||
|
||||
SYST(1980, polysix, 0, 0, polysix, polysix, polysix_state, empty_init, "Korg", "Polysix Programmable Polyphonic Synthesizer", MACHINE_IS_SKELETON)
|
||||
|
Loading…
Reference in New Issue
Block a user