summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author mahlemiut <bsr@xnet.co.nz>2017-06-24 12:45:01 +1200
committer mahlemiut <bsr@xnet.co.nz>2017-06-24 12:45:25 +1200
commit478e2228869cc819e6a7818bb09ba8236e4ebe83 (patch)
treeddcdb81984beecd8df8859a796d111e4bfe90cef
parent97889a232fc814c7e113bd2c0e4158dede7e3498 (diff)
ym3802: added preliminary MIDI clock timer and click counter, gets Mahou Daisakusen (x68k) to play MIDI music.
-rw-r--r--src/devices/machine/ym3802.cpp68
-rw-r--r--src/devices/machine/ym3802.h9
2 files changed, 68 insertions, 9 deletions
diff --git a/src/devices/machine/ym3802.cpp b/src/devices/machine/ym3802.cpp
index 245cfa1ff13..02abecae23b 100644
--- a/src/devices/machine/ym3802.cpp
+++ b/src/devices/machine/ym3802.cpp
@@ -8,8 +8,8 @@
* - Transmit Idle detection
* - IRx/ITx (used for MIDI system messages)
* - FSK modulation
- * - Timers
- * - Interrupts (except for Tx Buffer Empty)
+ * - Timers (MIDI clock timer and Click counter are working but not guaranteed to be perfectly accurate)
+ * - Interrupts (except for Tx Buffer Empty, MIDI clock detect, Click Counter)
*/
#include "emu.h"
@@ -39,7 +39,8 @@ void ym3802_device::device_start()
m_txd_handler.resolve_safe();
m_rxd_handler.resolve_safe(0xff);
m_clock_timer = timer_alloc(TIMER_SYSTEM_CLOCK);
- m_midi_timer = timer_alloc(TIMER_MIDI_CLOCK);
+ m_midi_timer = timer_alloc(TIMER_TX_CLOCK);
+ m_midi_counter_timer = timer_alloc(TIMER_MIDI_CLOCK);
save_item(NAME(m_reg));
}
@@ -58,9 +59,12 @@ void ym3802_device::device_timer(emu_timer &timer, device_timer_id id, int param
// TODO: support clock and timers
switch(id)
{
- case TIMER_MIDI_CLOCK:
+ case TIMER_TX_CLOCK:
transmit_clk();
break;
+ case TIMER_MIDI_CLOCK:
+ midi_clk();
+ break;
}
}
@@ -112,10 +116,35 @@ void ym3802_device::transmit_clk()
}
}
+void ym3802_device::midi_clk()
+{
+ if(m_midi_counter_base > 1) // counter is not guaranteed to work if set to 0 or 1.
+ {
+ if(m_midi_counter == 0)
+ {
+ m_midi_counter = m_midi_counter_base; // reload timer
+ if(m_reg[REG_IMR] & 0x08) // if IRQ1 is set to MIDI clock detect
+ set_irq(IRQ_MIDI_CLK);
+ if(m_click_counter_base != 0)
+ {
+ m_click_counter--;
+ if(m_click_counter == 0)
+ {
+ m_click_counter = m_click_counter_base;
+ if(!(m_reg[REG_IMR] & 0x08)) // if IRQ1 is set to click counter
+ set_irq(IRQ_CLICK);
+ }
+ }
+ }
+ else
+ m_midi_counter--;
+ }
+}
+
void ym3802_device::reset_midi_timer()
{
uint64_t rate;
- uint8_t divisor = m_reg[REG_RRR] & 0x1f;
+ uint8_t divisor = m_reg[REG_TRR] & 0x1f;
if(!(divisor & 0x10))
{
@@ -221,11 +250,28 @@ WRITE8_MEMBER(ym3802_device::write)
switch(offset + (bank * 10))
{
case REG_IOR:
- popmessage("IOR vector write %02\n",data);
+ logerror("IOR vector write %02\n",data);
break;
case REG_IER:
logerror("IER set to %02x\n",data);
break;
+ case REG_DCR:
+ if(data & 0x20)
+ {
+ if((data & 0x07) == 2)
+ {
+ uint64_t rate = (m_reg[REG_CCR] & 0x02) ? m_clkm_rate / 4 : m_clkm_rate / 8;
+
+ // start message to click counter
+ m_midi_counter_timer->adjust(attotime::from_hz(rate),0,attotime::from_hz(rate));
+ }
+ if((data & 0x07) == 3)
+ {
+ // stop message to click counter
+ m_midi_counter_timer->adjust(attotime::zero,0,attotime::never);
+ }
+ }
+ break;
case REG_TMR:
set_comms_mode();
break;
@@ -246,13 +292,19 @@ WRITE8_MEMBER(ym3802_device::write)
//popmessage("General counter set to %i\n",m_general_counter);
break;
case REG_MTR_LOW:
- m_midi_counter = (m_midi_counter & 0xff00) | data;
+ m_midi_counter_base = (m_midi_counter & 0xff00) | data;
+ m_midi_counter = m_midi_counter_base;
//popmessage("MIDI counter set to %i\n",m_midi_counter);
break;
case REG_MTR_HIGH:
- m_midi_counter = (m_midi_counter & 0x00ff) | ((data & 0x3f) << 8);
+ m_midi_counter_base = (m_midi_counter & 0x00ff) | ((data & 0x3f) << 8);
+ m_midi_counter = m_midi_counter_base;
//popmessage("MIDI counter set to %i\n",m_midi_counter);
break;
+ case REG_CDR:
+ m_click_counter_base = data & 0x7f;
+ m_click_counter = m_click_counter_base;
+ break;
}
}
}
diff --git a/src/devices/machine/ym3802.h b/src/devices/machine/ym3802.h
index 003c52a759f..c9807186937 100644
--- a/src/devices/machine/ym3802.h
+++ b/src/devices/machine/ym3802.h
@@ -126,10 +126,12 @@ private:
enum
{
TIMER_SYSTEM_CLOCK = 0x200, // CLK input - anywhere from 1MHz up to 4MHz
- TIMER_MIDI_CLOCK, // CLKM input - usually either 1MHz or 0.5MHz, or CLKF input - usually 614.4kHz
+ TIMER_TX_CLOCK,
+ TIMER_MIDI_CLOCK // CLKM input - usually either 1MHz or 0.5MHz, or CLKF input - usually 614.4kHz
};
void transmit_clk();
+ void midi_clk();
void reset_midi_timer();
void set_comms_mode();
void set_irq(uint8_t irq);
@@ -140,6 +142,7 @@ private:
devcb_read_line m_rxd_handler;
emu_timer* m_clock_timer;
emu_timer* m_midi_timer;
+ emu_timer* m_midi_counter_timer;
std::vector<uint8_t> m_reg;
uint8_t m_wdr;
@@ -147,6 +150,10 @@ private:
uint8_t m_irq_status;
uint16_t m_general_counter;
uint16_t m_midi_counter;
+ uint16_t m_midi_counter_base;
+ uint8_t m_midi_counter_divider;
+ uint8_t m_click_counter;
+ uint8_t m_click_counter_base;
uint8_t m_vector;
std::queue<uint8_t> m_tx_fifo;