summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/votrax.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/votrax.cpp')
-rw-r--r--src/devices/sound/votrax.cpp86
1 files changed, 57 insertions, 29 deletions
diff --git a/src/devices/sound/votrax.cpp b/src/devices/sound/votrax.cpp
index 067e639ed78..f1da1134415 100644
--- a/src/devices/sound/votrax.cpp
+++ b/src/devices/sound/votrax.cpp
@@ -25,12 +25,27 @@ tp1 = phi clock (tied to f2q rom access)
#include "emu.h"
#include "votrax.h"
+#define LOG_PHONE (1U << 1)
+#define LOG_COMMIT (1U << 2)
+#define LOG_INT (1U << 3)
+#define LOG_TICK (1U << 4)
+#define LOG_FILTER (1U << 5)
-DEFINE_DEVICE_TYPE(VOTRAX_SC01, votrax_sc01_device, "votrax", "Votrax SC-01")
+//#define VERBOSE (LOG_GENERAL | LOG_PHONE)
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(VOTRAX_SC01, votrax_sc01_device, "votrsc01", "Votrax SC-01")
+DEFINE_DEVICE_TYPE(VOTRAX_SC01A, votrax_sc01a_device, "votrsc01a", "Votrax SC-01-A")
// ROM definition for the Votrax phone ROM
ROM_START( votrax_sc01 )
ROM_REGION64_LE( 0x200, "internal", 0 )
+ ROM_LOAD( "sc01.bin", 0x000, 0x200, CRC(528d1c57) SHA1(268b5884dce04e49e2376df3e2dc82e852b708c1) )
+ROM_END
+
+ROM_START( votrax_sc01a )
+ ROM_REGION64_LE( 0x200, "internal", 0 )
ROM_LOAD( "sc01a.bin", 0x000, 0x200, CRC(fc416227) SHA1(1d6da90b1807a01b5e186ef08476119a862b5e6d) )
ROM_END
@@ -74,9 +89,14 @@ const double votrax_sc01_device::s_glottal_wave[9] =
1/7.0
};
-
votrax_sc01_device::votrax_sc01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, VOTRAX_SC01, tag, owner, clock),
+ : votrax_sc01_device(mconfig, VOTRAX_SC01, tag, owner, clock)
+{
+}
+
+// overridable type for subclass
+votrax_sc01_device::votrax_sc01_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock),
device_sound_interface(mconfig, *this),
m_stream(nullptr),
m_rom(*this, "internal"),
@@ -84,6 +104,11 @@ votrax_sc01_device::votrax_sc01_device(const machine_config &mconfig, const char
{
}
+votrax_sc01a_device::votrax_sc01a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : votrax_sc01_device(mconfig, VOTRAX_SC01A, tag, owner, clock)
+{
+}
+
void votrax_sc01_device::write(uint8_t data)
{
// flush out anything currently processing
@@ -95,9 +120,10 @@ void votrax_sc01_device::write(uint8_t data)
m_phone = data & 0x3f;
if(m_phone != prev || m_phone != 0x3f)
- logerror("phone %02x.%d %s\n", m_phone, m_inflection, s_phone_table[m_phone]);
+ LOGMASKED(LOG_PHONE, "phone %02x.%d %s\n", m_phone, m_inflection, s_phone_table[m_phone]);
m_ar_state = CLEAR_LINE;
+ m_ar_cb(m_ar_state);
// Schedule a commit/ar reset at roughly 0.1ms in the future (one
// phi1 transition followed by the rom extra state in practice),
@@ -157,6 +183,11 @@ const tiny_rom_entry *votrax_sc01_device::device_rom_region() const
return ROM_NAME( votrax_sc01 );
}
+const tiny_rom_entry *votrax_sc01a_device::device_rom_region() const
+{
+ return ROM_NAME( votrax_sc01a );
+}
+
//-------------------------------------------------
// device_start - handle device startup
@@ -169,10 +200,9 @@ void votrax_sc01_device::device_start()
m_sclock = m_mainclock / 18.0;
m_cclock = m_mainclock / 36.0;
m_stream = stream_alloc(0, 1, m_sclock);
- m_timer = timer_alloc();
+ m_timer = timer_alloc(FUNC(votrax_sc01_device::phone_tick), this);
// reset outputs
- m_ar_cb.resolve_safe();
m_ar_state = ASSERT_LINE;
// save inputs
@@ -330,10 +360,10 @@ void votrax_sc01_device::device_clock_changed()
//-------------------------------------------------
-// device_timer - handle device timer
+// phone_tick - process transitions
//-------------------------------------------------
-void votrax_sc01_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(votrax_sc01_device::phone_tick)
{
m_stream->update();
@@ -387,8 +417,7 @@ void votrax_sc01_device::phone_commit()
// Hard-wired on the die, not an actual part of the rom.
m_rom_pause = (m_phone == 0x03) || (m_phone == 0x3e);
- if(0)
- logerror("commit fa=%x va=%x fc=%x f1=%x f2=%x f2q=%x f3=%x dur=%02x cld=%x vd=%d cl=%d pause=%d\n", m_rom_fa, m_rom_va, m_rom_fc, m_rom_f1, m_rom_f2, m_rom_f2q, m_rom_f3, m_rom_duration, m_rom_cld, m_rom_vd, m_rom_closure, m_rom_pause);
+ LOGMASKED(LOG_COMMIT, "commit fa=%x va=%x fc=%x f1=%x f2=%x f2q=%x f3=%x dur=%02x cld=%x vd=%d cl=%d pause=%d\n", m_rom_fa, m_rom_va, m_rom_fc, m_rom_f1, m_rom_f2, m_rom_f2q, m_rom_f3, m_rom_duration, m_rom_cld, m_rom_vd, m_rom_closure, m_rom_pause);
// That does not happen in the sc01(a) rom, but let's
// cover our behind.
@@ -438,29 +467,30 @@ void votrax_sc01_device::chip_update()
// The formants are frozen on a pause phone unless both voice and
// noise volumes are zero.
if(tick_208 && (!m_rom_pause || !(m_filt_fa || m_filt_va))) {
- // interpolate(m_cur_va, m_rom_va);
+ // interpolate(m_cur_va, m_rom_va);
interpolate(m_cur_fc, m_rom_fc);
interpolate(m_cur_f1, m_rom_f1);
interpolate(m_cur_f2, m_rom_f2);
interpolate(m_cur_f2q, m_rom_f2q);
interpolate(m_cur_f3, m_rom_f3);
- // logerror("int fa=%x va=%x fc=%x f1=%x f2=%02x f2q=%02x f3=%x\n", m_cur_fa >> 4, m_cur_va >> 4, m_cur_fc >> 4, m_cur_f1 >> 4, m_cur_f2 >> 3, m_cur_f2q >> 4, m_cur_f3 >> 4);
+ LOGMASKED(LOG_INT, "int fa=%x va=%x fc=%x f1=%x f2=%02x f2q=%02x f3=%x\n", m_cur_fa >> 4, m_cur_va >> 4, m_cur_fc >> 4, m_cur_f1 >> 4, m_cur_f2 >> 3, m_cur_f2q >> 4, m_cur_f3 >> 4);
}
// Non-formant update. Same bug there, va should be updated, not fc.
if(tick_625) {
if(m_ticks >= m_rom_vd)
interpolate(m_cur_fa, m_rom_fa);
- if(m_ticks >= m_rom_cld)
- // interpolate(m_cur_fc, m_rom_fc);
+ if(m_ticks >= m_rom_cld) {
+ // interpolate(m_cur_fc, m_rom_fc);
interpolate(m_cur_va, m_rom_va);
- // logerror("int fa=%x va=%x fc=%x f1=%x f2=%02x f2q=%02x f3=%x\n", m_cur_fa >> 4, m_cur_va >> 4, m_cur_fc >> 4, m_cur_f1 >> 4, m_cur_f2 >> 3, m_cur_f2q >> 4, m_cur_f3 >> 4);
+ LOGMASKED(LOG_INT, "int fa=%x va=%x fc=%x f1=%x f2=%02x f2q=%02x f3=%x\n", m_cur_fa >> 4, m_cur_va >> 4, m_cur_fc >> 4, m_cur_f1 >> 4, m_cur_f2 >> 3, m_cur_f2q >> 4, m_cur_f3 >> 4);
+ }
}
// Closure counter, reset every other tick in theory when not
// active (on the extra rom cycle).
//
- // The closure level is immediatly used in the analog path,
+ // The closure level is immediately used in the analog path,
// there's no pitch synchronization.
if(!m_cur_closure && (m_filt_fa || m_filt_va))
@@ -489,7 +519,7 @@ void votrax_sc01_device::chip_update()
m_noise = ((m_noise << 1) & 0x7ffe) | inp;
m_cur_noise = !(((m_noise >> 14) ^ (m_noise >> 13)) & 1);
- // logerror("%s tick %02x.%03x 625=%d 208=%d pitch=%02x.%x ns=%04x ni=%d noise=%d cl=%x.%x clf=%d/%d\n", machine().time().to_string(), m_ticks, m_phonetick, tick_625, tick_208, m_pitch >> 3, m_pitch & 7, m_noise, inp, m_cur_noise, m_closure >> 2, m_closure & 3, m_rom_closure, m_cur_closure);
+ LOGMASKED(LOG_TICK, "%s tick %02x.%03x 625=%d 208=%d pitch=%02x.%x ns=%04x ni=%d noise=%d cl=%x.%x clf=%d/%d\n", machine().time().to_string(), m_ticks, m_phonetick, tick_625, tick_208, m_pitch >> 3, m_pitch & 7, m_noise, inp, m_cur_noise, m_closure >> 2, m_closure & 3, m_rom_closure, m_cur_closure);
}
void votrax_sc01_device::filters_commit(bool force)
@@ -562,10 +592,8 @@ void votrax_sc01_device::filters_commit(bool force)
14083);
}
- if(0)
- if(m_filt_fa || m_filt_va || m_filt_fc || m_filt_f1 || m_filt_f2 || m_filt_f2q || m_filt_f3)
- logerror("filter fa=%x va=%x fc=%x f1=%x f2=%02x f2q=%x f3=%x\n",
- m_filt_fa, m_filt_va, m_filt_fc, m_filt_f1, m_filt_f2, m_filt_f2q, m_filt_f3);
+ if(m_filt_fa | m_filt_va | m_filt_fc | m_filt_f1 | m_filt_f2 | m_filt_f2q | m_filt_f3)
+ LOGMASKED(LOG_FILTER, "filter fa=%x va=%x fc=%x f1=%x f2=%02x f2q=%x f3=%x\n", m_filt_fa, m_filt_va, m_filt_fc, m_filt_f1, m_filt_f2, m_filt_f2q, m_filt_f3);
}
stream_buffer::sample_t votrax_sc01_device::analog_calc()
@@ -632,7 +660,7 @@ stream_buffer::sample_t votrax_sc01_device::analog_calc()
vn = apply_filter(m_vn_5, m_vn_6, m_fx_a, m_fx_b);
shift_hist(vn, m_vn_6);
- return vn*1.5;
+ return vn*0.35;
}
/*
@@ -662,16 +690,16 @@ stream_buffer::sample_t votrax_sc01_device::analog_calc()
defined as the ratio Vo/Vi. To do that, you use some properties:
- The intensity through an element is equal to the voltage
- difference through the element divided by the impedence
+ difference through the element divided by the impedance
- - The impedence of a resistance is equal to its resistance
+ - The impedance of a resistance is equal to its resistance
- - The impedence of a capacitor is 1/(s*C) where C is its capacitance
+ - The impedance of a capacitor is 1/(s*C) where C is its capacitance
- - The impedence of elements in series is the sum of the impedences
+ - The impedance of elements in series is the sum of their impedances
- - The impedence of elements in parallel is the inverse of the sum of
- the inverses
+ - The impedance of elements in parallel is the inverse of the sum of
+ their inverses
- The sum of all intensities flowing into a node is 0 (there's no
charge accumulation in a wire)
@@ -716,7 +744,7 @@ stream_buffer::sample_t votrax_sc01_device::analog_calc()
| H(s) = -------------------------
| 1 + k[1]*s + k[2]*s^2
- We can always reintroduce the global multipler later, and it's 1 in
+ We can always reintroduce the global multiplier later, and it's 1 in
most of our cases anyway.
The we pose: