From 19c5c5bff841e226ca672d5c4b6e79dc0a8b52ec Mon Sep 17 00:00:00 2001 From: hap Date: Thu, 29 Feb 2024 01:52:28 +0100 Subject: added preliminary OKI MSM6588 ADPCM Recorder device --- scripts/src/sound.lua | 10 +- src/devices/sound/okim6588.cpp | 225 +++++++++++++++++++++++++++++++++++++++++ src/devices/sound/okim6588.h | 88 ++++++++++++++++ src/devices/video/hd61603.cpp | 2 +- src/devices/video/hd61603.h | 2 +- 5 files changed, 324 insertions(+), 3 deletions(-) create mode 100644 src/devices/sound/okim6588.cpp create mode 100644 src/devices/sound/okim6588.h diff --git a/scripts/src/sound.lua b/scripts/src/sound.lua index fe1b86137cd..522aff46042 100644 --- a/scripts/src/sound.lua +++ b/scripts/src/sound.lua @@ -692,11 +692,12 @@ end --@src/devices/sound/msm5232.h,SOUNDS["MSM5232"] = true --@src/devices/sound/okim6376.h,SOUNDS["OKIM6376"] = true --@src/devices/sound/okim6295.h,SOUNDS["OKIM6295"] = true +--@src/devices/sound/okim6588.h,SOUNDS["OKIM6588"] = true --@src/devices/sound/okim9810.h,SOUNDS["OKIM9810"] = true --@src/devices/sound/okiadpcm.h,SOUNDS["OKIADPCM"] = true --------------------------------------------------- -if (SOUNDS["OKIM6258"]~=null or SOUNDS["OKIM6295"]~=null or SOUNDS["OKIM9810"]~=null or SOUNDS["I5000_SND"]~=null or SOUNDS["OKIADPCM"]~=null) then +if (SOUNDS["OKIM6258"]~=null or SOUNDS["OKIM6295"]~=null or SOUNDS["OKIM6588"]~=null or SOUNDS["OKIM9810"]~=null or SOUNDS["I5000_SND"]~=null or SOUNDS["OKIADPCM"]~=null) then files { MAME_DIR .. "src/devices/sound/okiadpcm.cpp", MAME_DIR .. "src/devices/sound/okiadpcm.h", @@ -738,6 +739,13 @@ if (SOUNDS["OKIM6258"]~=null) then } end +if (SOUNDS["OKIM6588"]~=null) then + files { + MAME_DIR .. "src/devices/sound/okim6588.cpp", + MAME_DIR .. "src/devices/sound/okim6588.h", + } +end + if (SOUNDS["OKIM9810"]~=null) then files { MAME_DIR .. "src/devices/sound/okim9810.cpp", diff --git a/src/devices/sound/okim6588.cpp b/src/devices/sound/okim6588.cpp new file mode 100644 index 00000000000..7704c61d315 --- /dev/null +++ b/src/devices/sound/okim6588.cpp @@ -0,0 +1,225 @@ +// license:BSD-3-Clause +// copyright-holders:hap +/* + +OKI MSM6588 ADPCM Recorder + +TODO: +- it only supports MCU mode EXT playback, nothing else emulated yet +- status register read (eg. BUSY flag) + +*/ + +#include "emu.h" +#include "okim6588.h" + + +DEFINE_DEVICE_TYPE(OKIM6588, okim6588_device, "okim6588", "OKI MSM6588 ADPCM Recorder") + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +okim6588_device::okim6588_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, OKIM6588, tag, owner, clock), + device_sound_interface(mconfig, *this), + m_write_mon(*this), + m_chip_mode(CHIP_MODE_STANDALONE) +{ } + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +// allow save_item on a non-fundamental type +ALLOW_SAVE_TYPE(okim6588_device::chip_mode); +ALLOW_SAVE_TYPE(okim6588_device::command_state); +ALLOW_SAVE_TYPE(okim6588_device::run_state); + +void okim6588_device::device_start() +{ + // initialize + m_stream = stream_alloc(0, 1, clock() / 128); + + m_adpcm_timer = timer_alloc(FUNC(okim6588_device::clock_adpcm), this); + m_mon_timer = timer_alloc(FUNC(okim6588_device::set_mon), this); + + m_command_state = COMMAND_READY; + m_run_state = RUN_STOP; + m_adpcm_data = 0; + + m_vds_bit = (m_chip_mode == CHIP_MODE_MCU) ? 1 : 0; + m_samp_fdiv = 512; + m_rec_mode = false; + + // register for savestates + save_item(NAME(m_chip_mode)); + save_item(NAME(m_command_state)); + save_item(NAME(m_run_state)); + save_item(NAME(m_adpcm_data)); + save_item(NAME(m_adpcm.m_signal)); + save_item(NAME(m_adpcm.m_step)); + save_item(NAME(m_rec_mode)); + save_item(NAME(m_samp_fdiv)); + save_item(NAME(m_vds_bit)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void okim6588_device::device_reset() +{ + m_command_state = COMMAND_READY; + m_run_state = RUN_STOP; + reset_adpcm(); + + m_adpcm_timer->adjust(attotime::never); + m_mon_timer->adjust(attotime::never); + m_write_mon(0); +} + + +//------------------------------------------------- +// internal handlers +//------------------------------------------------- + +void okim6588_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) +{ + // simply fill the buffer with the current sample + outputs[0].fill(m_adpcm.output() / 2048.0); +} + +TIMER_CALLBACK_MEMBER(okim6588_device::clock_adpcm) +{ + switch (m_run_state) + { + case RUN_STOP: + reset_adpcm(); + break; + + case RUN_PLAY_EXT: + // strobe MON + m_write_mon(1); + m_mon_timer->adjust(attotime::from_ticks(m_samp_fdiv / 4, clock())); + m_command_state = COMMAND_EXT; + + m_stream->update(); + get_adpcm_sample(m_adpcm_data); + break; + + default: + break; + } + + if (m_run_state != RUN_STOP && m_run_state != RUN_PAUSE) + m_adpcm_timer->adjust(attotime::from_ticks(m_samp_fdiv, clock())); +} + +TIMER_CALLBACK_MEMBER(okim6588_device::set_mon) +{ + m_write_mon(param ? 1 : 0); +} + +s32 okim6588_device::get_adpcm_sample(u8 data) +{ + u8 mask = m_vds_bit ? 0xf : 0xe; + return m_adpcm.clock(data & mask); +} + +void okim6588_device::reset_adpcm() +{ + m_stream->update(); + m_adpcm_data = 0; + m_adpcm.reset(); +} + + +//------------------------------------------------- +// public handlers +//------------------------------------------------- + +u8 okim6588_device::data_r() +{ + if (m_chip_mode != CHIP_MODE_MCU) + return 0; + + return 0; +} + +void okim6588_device::data_w(u8 data) +{ + if (m_chip_mode != CHIP_MODE_MCU) + return; + + data &= 0xf; + + switch (m_command_state) + { + case COMMAND_READY: + switch (data & 0xf) + { + // NOP + case 0x0: + break; + + // PLAY/REC + case 0x2: case 0x3: + m_rec_mode = bool(data & 1); + break; + + // STOP + case 0x5: + m_run_state = RUN_STOP; + break; + + // SAMP + case 0x6: + m_command_state = COMMAND_SAMP; + break; + + // VDS + case 0xc: + m_command_state = COMMAND_VDS; + break; + + // EXT + case 0xb: + m_run_state = m_rec_mode ? RUN_RECORD_EXT : RUN_PLAY_EXT; + reset_adpcm(); + + // minimum delay is 1 sample + m_adpcm_timer->adjust(attotime::from_ticks(m_samp_fdiv, clock())); + m_command_state = COMMAND_EXT; + break; + + default: + break; + } + break; + + case COMMAND_SAMP: + { + static const u16 div[4] = { 1024, 768, 640, 512 }; + m_samp_fdiv = div[data & 3]; + m_command_state = COMMAND_READY; + break; + } + + case COMMAND_EXT: + m_adpcm_data = data; + m_command_state = COMMAND_READY; + break; + + case COMMAND_VDS: + m_vds_bit = BIT(data, 2); + m_command_state = COMMAND_READY; + break; + + default: + // shouldn't get here + break; + } +} diff --git a/src/devices/sound/okim6588.h b/src/devices/sound/okim6588.h new file mode 100644 index 00000000000..7382902c3d8 --- /dev/null +++ b/src/devices/sound/okim6588.h @@ -0,0 +1,88 @@ +// license:BSD-3-Clause +// copyright-holders:hap +/* + + OKI MSM6588 ADPCM Recorder + +*/ + +#ifndef MAME_SOUND_OKIM6588_H +#define MAME_SOUND_OKIM6588_H + +#pragma once + +#include "sound/okiadpcm.h" + + +class okim6588_device : public device_t, public device_sound_interface +{ +public: + okim6588_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // configuration helpers + auto write_mon() { return m_write_mon.bind(); } + void set_mcum_pin(int state) { m_chip_mode = state ? CHIP_MODE_MCU : CHIP_MODE_STANDALONE; } + + // D0-D3 (MCU mode) + void data_w(u8 data); + u8 data_r(); + +protected: + // device_t implementation + virtual void device_start() override; + virtual void device_reset() override; + + virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; + +private: + enum chip_mode : u8 + { + CHIP_MODE_STANDALONE = 0, + CHIP_MODE_MCU + }; + + enum command_state : u8 + { + COMMAND_READY = 0, + COMMAND_SAMP, + COMMAND_EXT, + COMMAND_VDS + }; + + enum run_state : u8 + { + RUN_STOP = 0, + RUN_PAUSE, + RUN_PLAY_SERIAL, + RUN_PLAY_EXT, + RUN_RECORD_SERIAL, + RUN_RECORD_EXT, + }; + + devcb_write_line m_write_mon; + + chip_mode m_chip_mode; + command_state m_command_state; + run_state m_run_state; + + sound_stream *m_stream; + + u8 m_adpcm_data; + oki_adpcm_state m_adpcm; + bool m_rec_mode; + u16 m_samp_fdiv; + u8 m_vds_bit; + + emu_timer *m_adpcm_timer; + emu_timer *m_mon_timer; + + TIMER_CALLBACK_MEMBER(clock_adpcm); + TIMER_CALLBACK_MEMBER(set_mon); + s32 get_adpcm_sample(u8 data); + void reset_adpcm(); +}; + + +DECLARE_DEVICE_TYPE(OKIM6588, okim6588_device) + +#endif // MAME_SOUND_OKIM6588_H diff --git a/src/devices/video/hd61603.cpp b/src/devices/video/hd61603.cpp index bdc2cd7aa66..d9187fd78fa 100644 --- a/src/devices/video/hd61603.cpp +++ b/src/devices/video/hd61603.cpp @@ -14,7 +14,7 @@ TODO: */ #include "emu.h" -#include "video/hd61603.h" +#include "hd61603.h" DEFINE_DEVICE_TYPE(HD61603, hd61603_device, "hd61603", "Hitachi HD61603 LCD Driver") diff --git a/src/devices/video/hd61603.h b/src/devices/video/hd61603.h index 8de7c879761..bffb2b73848 100644 --- a/src/devices/video/hd61603.h +++ b/src/devices/video/hd61603.h @@ -45,7 +45,7 @@ public: void data_w(u8 data); protected: - // device-level overrides + // device_t implementation virtual void device_start() override; virtual void device_reset() override; -- cgit v1.2.3