diff options
author | ajrhacker <ajrhacker@users.noreply.github.com> | 2020-06-17 09:20:23 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-17 09:20:23 -0400 |
commit | 1d057a673f379c4bbd6ac850862de46b68b5dfe7 (patch) | |
tree | f9a6a659755f4a0713d1484a38f8927dca19feb1 | |
parent | 73e4ae4251a562ee020286bf13e21e6f6a1fdfb9 (diff) | |
parent | 3ff2212deb042627098bf825a8663702a5311702 (diff) |
Merge pull request #6835 from cam900/ics2115_space
ics2115.cpp: Use device_memory_interface for fetch external samples
-rw-r--r-- | src/devices/sound/ics2115.cpp | 148 | ||||
-rw-r--r-- | src/devices/sound/ics2115.h | 32 |
2 files changed, 132 insertions, 48 deletions
diff --git a/src/devices/sound/ics2115.cpp b/src/devices/sound/ics2115.cpp index 040955a3064..b754f18c716 100644 --- a/src/devices/sound/ics2115.cpp +++ b/src/devices/sound/ics2115.cpp @@ -1,14 +1,24 @@ // license:BSD-3-Clause // copyright-holders:Alex Marshall,nimitz,austere -//ICS2115 by Raiden II team (c) 2010 -//members: austere, nimitz, Alex Marshal -// -//Original driver by O. Galibert, ElSemi -// -//Use tab size = 4 for your viewing pleasure. +/* + ICS2115 by Raiden II team (c) 2010 + members: austere, nimitz, Alex Marshal + + Original driver by O. Galibert, ElSemi + + Use tab size = 4 for your viewing pleasure. + + TODO: + - Implement Panning, Chip has support stereo + - Verify BYTE/ROMEN pin behaviors + - DRAM, DMA, MIDI interface is unimplemented + - Verify interrupt, envelope, timer period + - Verify unemulated registers +*/ #include "emu.h" #include "ics2115.h" +#include <algorithm> #include <cmath> //#define ICS2115_DEBUG @@ -18,15 +28,34 @@ DEFINE_DEVICE_TYPE(ICS2115, ics2115_device, "ics2115", "ICS2115 WaveFront Synthesizer") ics2115_device::ics2115_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : device_t(mconfig, ICS2115, tag, owner, clock), - device_sound_interface(mconfig, *this), m_stream(nullptr), - m_rom(*this, DEVICE_SELF), - m_irq_cb(*this), m_active_osc(0), m_osc_select(0), m_reg_select(0), m_irq_enabled(0), m_irq_pending(0), m_irq_on(false), m_vmode(0) + : device_t(mconfig, ICS2115, tag, owner, clock) + , device_sound_interface(mconfig, *this) + , device_memory_interface(mconfig, *this) + , m_data_config("data", ENDIANNESS_LITTLE, 8, 24) // 24 bit address bus, 8 bit data bus(ROM), 11 bit address bus, 8 bit data bus, 4 banks(DRAM) + , m_stream(nullptr) + , m_rom(*this, DEVICE_SELF) + , m_irq_cb(*this) + , m_active_osc(0) + , m_osc_select(0) + , m_reg_select(0) + , m_irq_enabled(0) + , m_irq_pending(0) + , m_irq_on(false) + , m_vmode(0) { } +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + void ics2115_device::device_start() { + if (m_rom && !has_configured_map(0)) + space(0).install_rom(0, std::min<offs_t>((1 << 24) - 1, m_rom.bytes()), m_rom.target()); + + space(0).cache(m_cache); + m_timer[0].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ics2115_device::timer_cb_0),this), this); m_timer[1].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ics2115_device::timer_cb_1),this), this); m_stream = machine().sound().stream_alloc(*this, 0, 2, clock() / (32 * 32)); @@ -97,6 +126,9 @@ void ics2115_device::device_start() } } +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- void ics2115_device::device_reset() { @@ -137,11 +169,29 @@ void ics2115_device::device_reset() } } + +//------------------------------------------------- +// device_clock_changed - called if the clock +// changes +//------------------------------------------------- + void ics2115_device::device_clock_changed() { m_stream->set_sample_rate(clock() / ((m_active_osc + 1) * 32)); } + +//------------------------------------------------- +// memory_space_config - return a description of +// any address spaces owned by this device +//------------------------------------------------- + +device_memory_interface::space_config_vector ics2115_device::memory_space_config() const +{ + return space_config_vector{ std::make_pair(0, &m_data_config) }; +} + + //TODO: improve using next-state logic from column 126 of patent 5809466 int ics2115_device::ics2115_voice::update_volume_envelope() { @@ -263,39 +313,39 @@ int ics2115_device::ics2115_voice::update_oscillator() return ret; } -//TODO: proper interpolation for uLaw (fill_output doesn't use this) and 8-bit samples (looping) +//TODO: proper interpolation for 8-bit samples (looping) stream_sample_t ics2115_device::get_sample(ics2115_voice& voice) { - u32 curaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.acc >> 12); + u32 curaddr = voice.osc.acc >> 12; u32 nextaddr; if (voice.state.bitflags.on && voice.osc_conf.bitflags.loop && !voice.osc_conf.bitflags.loop_bidir && (voice.osc.left < (voice.osc.fc <<2))) { //logerror("C?[%x:%x]", voice.osc.left, voice.osc.acc); - nextaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.start >> 12); + nextaddr = voice.osc.start >> 12; } else nextaddr = curaddr + 2; - s16 sample1, sample2; - if (voice.osc_conf.bitflags.eightbit) + if (voice.osc_conf.bitflags.ulaw) { - sample1 = ((s8)m_rom[curaddr]) << 8; - sample2 = ((s8)m_rom[curaddr + 1]) << 8; + sample1 = m_ulaw[read_sample(voice, curaddr)]; + sample2 = m_ulaw[read_sample(voice, curaddr + 1)]; + } + else if (voice.osc_conf.bitflags.eightbit) + { + sample1 = ((s8)read_sample(voice, curaddr)) << 8; + sample2 = ((s8)read_sample(voice, curaddr + 1)) << 8; } else { - sample1 = m_rom[curaddr + 0] | (((s8)m_rom[curaddr + 1]) << 8); - sample2 = m_rom[nextaddr+ 0] | (((s8)m_rom[nextaddr+ 1]) << 8); - //sample2 = m_rom[curaddr + 2] | (((s8)m_rom[curaddr + 3]) << 8); + sample1 = read_sample(voice, curaddr + 0) | (((s8)read_sample(voice, curaddr + 1)) << 8); + sample2 = read_sample(voice, nextaddr+ 0) | (((s8)read_sample(voice, nextaddr+ 1)) << 8); + //sample2 = read_sample(voice, curaddr + 2) | (((s8)read_sample(voice, curaddr + 3)) << 8); } - //no need for interpolation since it's around 1 note a cycle? - //if (voice.osc.fc >> 10) - // return sample1; - //linear interpolation as in US patent 6,246,774 B1, column 2 row 59 //LEN=1, BLEN=0, DIR=0, start+end interpolation s32 sample, diff; @@ -303,6 +353,10 @@ stream_sample_t ics2115_device::get_sample(ics2115_voice& voice) diff = sample2 - sample1; fract = (voice.osc.acc >> 3) & 0x1ff; + //no need for interpolation since it's around 1 note a cycle? + //if (!fract) + // return sample1; + sample = (((s32)sample1 << 9) + diff * fract) >> 9; //sample = sample1; return sample; @@ -349,14 +403,7 @@ int ics2115_device::fill_output(ics2115_voice& voice, stream_sample_t *outputs[2 //final output, even if they are not running. This means that whatever data value //that the voice is pointing at is contributing to the summation. //(austere note: this will of course fix some of the glitches due to multiple transition) - stream_sample_t sample; - if (voice.osc_conf.bitflags.ulaw) - { - u32 curaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.acc >> 12); - sample = m_ulaw[m_rom[curaddr]]; - } - else - sample = get_sample(voice); + stream_sample_t sample = get_sample(voice); //15-bit volume + (5-bit worth of 32 channel sum) + 16-bit samples = 4-bit extra if (!m_vmode || voice.playing()) @@ -396,11 +443,7 @@ void ics2115_device::sound_stream_update(sound_stream &stream, stream_sample_t * /* #ifdef ICS2115_DEBUG u32 curaddr = ((voice.osc.saddr << 20) & 0xffffff) | (voice.osc.acc >> 12); - stream_sample_t sample; - if (voice.osc_conf.bitflags.ulaw) - sample = m_ulaw[m_rom[curaddr]]; - else - sample = get_sample(voice); + stream_sample_t sample = get_sample(voice); logerror("[%06x=%04x]", curaddr, (s16)sample); #endif */ @@ -587,6 +630,9 @@ u16 ics2115_device::reg_read() ret = m_irq_pending & 3; break; + // case 0x48: // Accumulator Monitor Status + // case 0x49: // Accumulator Monitor Data + case 0x4a: // IRQ Pending ret = m_irq_pending; break; @@ -599,6 +645,17 @@ u16 ics2115_device::reg_read() ret = revision; break; + // case 0x4d: // System Control + + // case 0x50: // MIDI Data Register + // case 0x51: // MIDI Status Register + // case 0x52: // Host Data Register + // case 0x53: // Host Status Register + // case 0x54: // MIDI Emulation Interrupt Control + // case 0x55: // Host Emulation Interrupt Control + // case 0x56: // Host/MIDI Emulation Interrupt Status + // case 0x57: // Emulation Mode + default: #ifdef ICS2115_DEBUG logerror("ICS2115: Unhandled read %x\n", m_reg_select); @@ -794,6 +851,11 @@ void ics2115_device::reg_write(u16 data, u16 mem_mask) } break; + // case 0x44: // DMA Start Address Low (11:4) + // case 0x45: // DMA Start Address Low (19:12) + // case 0x46: // DMA Start Address Low (21:20) + // case 0x47: // DMA Control + case 0x4a: // IRQ Enable if (ACCESSING_BITS_0_7) { @@ -802,10 +864,22 @@ void ics2115_device::reg_write(u16 data, u16 mem_mask) } break; + // case 0x4c: // Memory Config + // case 0x4d: // System Control + case 0x4f: // Oscillator Address being Programmed if (ACCESSING_BITS_0_7) m_osc_select = (data & 0xff) % (1+m_active_osc); break; + + // case 0x50: // MIDI Data Register + // case 0x51: // MIDI Control Register + // case 0x52: // Host Data Register + // case 0x53: // Host Control Register + // case 0x54: // MIDI Emulation Interrupt Control + // case 0x55: // Host Emulation Interrupt Control + // case 0x57: // Emulation Mode + default: #ifdef ICS2115_DEBUG logerror("ICS2115: Unhandled write %x onto %x [voice = %d]\n", data, m_reg_select, m_osc_select); diff --git a/src/devices/sound/ics2115.h b/src/devices/sound/ics2115.h index 199b35b4929..8703c258344 100644 --- a/src/devices/sound/ics2115.h +++ b/src/devices/sound/ics2115.h @@ -12,7 +12,7 @@ // ======================> ics2115_device -class ics2115_device : public device_t, public device_sound_interface +class ics2115_device : public device_t, public device_sound_interface, public device_memory_interface { public: static constexpr feature_type imperfect_features() { return feature::SOUND; } // Incorrect/Unverified interrupt, interpolation; @@ -33,6 +33,20 @@ public: TIMER_CALLBACK_MEMBER(timer_cb_1); protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_clock_changed() override; + + // device_sound_interface overrides + virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; + + // device_memory_interface configuration + virtual space_config_vector memory_space_config() const override; + + address_space_config m_data_config; + +private: static constexpr u16 revision = 0x1; struct ics2115_voice { @@ -99,14 +113,6 @@ protected: void update_ramp(); }; - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_clock_changed() override; - - // internal callbacks - virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; - //internal register helper functions u16 reg_read(); void reg_write(u16 data, u16 mem_mask); @@ -117,10 +123,12 @@ protected: //stream helper functions int fill_output(ics2115_voice& voice, stream_sample_t *outputs[2], int samples); stream_sample_t get_sample(ics2115_voice& voice); + u8 read_sample(ics2115_voice& voice, u32 addr) { return m_cache.read_byte((voice.osc.saddr << 20) | (addr & 0xfffff)); } sound_stream *m_stream; // internal state + memory_access<24, 0, 0, ENDIANNESS_LITTLE>::cache m_cache; required_region_ptr<u8> m_rom; devcb_write_line m_irq_cb; @@ -141,8 +149,10 @@ protected: u8 m_irq_enabled, m_irq_pending; bool m_irq_on; - //Unknown variable, seems to be effected by 0x12. Further investigation - //Required. + /* + Unknown variable, seems to be effected by 0x12. Further investigation + Required. + */ u8 m_vmode; }; |