mirror of
https://github.com/holub/mame
synced 2025-07-03 09:06:08 +03:00
ti99: Model the Speech Synthesizer as an own unit, with an adapter board for the PEB.
This commit is contained in:
parent
ea2e33ad19
commit
f769905a02
@ -4176,8 +4176,8 @@ if (BUSES["TI99"]~=null) then
|
|||||||
MAME_DIR .. "src/devices/bus/ti99/peb/scsicard.h",
|
MAME_DIR .. "src/devices/bus/ti99/peb/scsicard.h",
|
||||||
MAME_DIR .. "src/devices/bus/ti99/peb/sidmaster.cpp",
|
MAME_DIR .. "src/devices/bus/ti99/peb/sidmaster.cpp",
|
||||||
MAME_DIR .. "src/devices/bus/ti99/peb/sidmaster.h",
|
MAME_DIR .. "src/devices/bus/ti99/peb/sidmaster.h",
|
||||||
MAME_DIR .. "src/devices/bus/ti99/peb/spchsyn.cpp",
|
MAME_DIR .. "src/devices/bus/ti99/peb/speechadapter.cpp",
|
||||||
MAME_DIR .. "src/devices/bus/ti99/peb/spchsyn.h",
|
MAME_DIR .. "src/devices/bus/ti99/peb/speechadapter.h",
|
||||||
MAME_DIR .. "src/devices/bus/ti99/peb/ti_32kmem.cpp",
|
MAME_DIR .. "src/devices/bus/ti99/peb/ti_32kmem.cpp",
|
||||||
MAME_DIR .. "src/devices/bus/ti99/peb/ti_32kmem.h",
|
MAME_DIR .. "src/devices/bus/ti99/peb/ti_32kmem.h",
|
||||||
MAME_DIR .. "src/devices/bus/ti99/peb/ti_fdc.cpp",
|
MAME_DIR .. "src/devices/bus/ti99/peb/ti_fdc.cpp",
|
||||||
@ -4192,6 +4192,8 @@ if (BUSES["TI99"]~=null) then
|
|||||||
MAME_DIR .. "src/devices/bus/ti99/peb/tn_usbsm.h",
|
MAME_DIR .. "src/devices/bus/ti99/peb/tn_usbsm.h",
|
||||||
MAME_DIR .. "src/devices/bus/ti99/sidecar/arcturus.cpp",
|
MAME_DIR .. "src/devices/bus/ti99/sidecar/arcturus.cpp",
|
||||||
MAME_DIR .. "src/devices/bus/ti99/sidecar/arcturus.h",
|
MAME_DIR .. "src/devices/bus/ti99/sidecar/arcturus.h",
|
||||||
|
MAME_DIR .. "src/devices/bus/ti99/sidecar/speechsyn.cpp",
|
||||||
|
MAME_DIR .. "src/devices/bus/ti99/sidecar/speechsyn.h",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -205,6 +205,9 @@ void datamux_device::setaddress_all(uint16_t addr)
|
|||||||
// Cartridge ROM
|
// Cartridge ROM
|
||||||
bool iscartrom = ((addr & 0xe000)==0x6000);
|
bool iscartrom = ((addr & 0xe000)==0x6000);
|
||||||
|
|
||||||
|
// Speech (1001 0wxx xxxx xxx0)
|
||||||
|
bool sbe = ((addr & 0xf801)==0x9000) && validaccess;
|
||||||
|
|
||||||
// Always deliver to GROM so that the select line may be cleared
|
// Always deliver to GROM so that the select line may be cleared
|
||||||
line_state gsq = isgrom? ASSERT_LINE : CLEAR_LINE;
|
line_state gsq = isgrom? ASSERT_LINE : CLEAR_LINE;
|
||||||
if (isgrom) m_grom_idle = false;
|
if (isgrom) m_grom_idle = false;
|
||||||
@ -228,6 +231,7 @@ void datamux_device::setaddress_all(uint16_t addr)
|
|||||||
// I/O port gets all accesses
|
// I/O port gets all accesses
|
||||||
m_memen_state = ASSERT_LINE;
|
m_memen_state = ASSERT_LINE;
|
||||||
m_ioport->memen_in(m_memen_state);
|
m_ioport->memen_in(m_memen_state);
|
||||||
|
m_ioport->sbe(sbe);
|
||||||
m_ioport->setaddress_dbin(addr, m_dbin);
|
m_ioport->setaddress_dbin(addr, m_dbin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@
|
|||||||
#include "splitter.h"
|
#include "splitter.h"
|
||||||
#include "bus/ti99/peb/peribox.h"
|
#include "bus/ti99/peb/peribox.h"
|
||||||
#include "bus/ti99/sidecar/arcturus.h"
|
#include "bus/ti99/sidecar/arcturus.h"
|
||||||
|
#include "bus/ti99/sidecar/speechsyn.h"
|
||||||
|
|
||||||
DEFINE_DEVICE_TYPE(TI99_IOPORT, bus::ti99::internal::ioport_device, "ti99_ioport", "TI-99 I/O Port")
|
DEFINE_DEVICE_TYPE(TI99_IOPORT, bus::ti99::internal::ioport_device, "ti99_ioport", "TI-99 I/O Port")
|
||||||
|
|
||||||
@ -149,6 +150,12 @@ void ioport_device::reset_in(int state)
|
|||||||
m_connected->reset_in(state);
|
m_connected->reset_in(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ioport_device::sbe(int state)
|
||||||
|
{
|
||||||
|
if (m_connected != nullptr)
|
||||||
|
m_connected->sbe(state);
|
||||||
|
}
|
||||||
|
|
||||||
void ioport_device::device_start()
|
void ioport_device::device_start()
|
||||||
{
|
{
|
||||||
if (m_connected != nullptr)
|
if (m_connected != nullptr)
|
||||||
@ -178,6 +185,7 @@ void ti99_ioport_options_plain(device_slot_interface &device)
|
|||||||
device.option_add("peb", TI99_PERIBOX);
|
device.option_add("peb", TI99_PERIBOX);
|
||||||
device.option_add("splitter", TI99_IOSPLIT);
|
device.option_add("splitter", TI99_IOSPLIT);
|
||||||
device.option_add("arcturus", TI99_ARCTURUS);
|
device.option_add("arcturus", TI99_ARCTURUS);
|
||||||
|
device.option_add("speechsyn", TI99_SPEECHSYN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ti99_ioport_options_evpc(device_slot_interface &device)
|
void ti99_ioport_options_evpc(device_slot_interface &device)
|
||||||
@ -185,6 +193,7 @@ void ti99_ioport_options_evpc(device_slot_interface &device)
|
|||||||
device.option_add("peb", TI99_PERIBOX_EV);
|
device.option_add("peb", TI99_PERIBOX_EV);
|
||||||
device.option_add("splitter", TI99_IOSPLIT);
|
device.option_add("splitter", TI99_IOSPLIT);
|
||||||
device.option_add("arcturus", TI99_ARCTURUS);
|
device.option_add("arcturus", TI99_ARCTURUS);
|
||||||
|
device.option_add("speechsyn", TI99_SPEECHSYN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for the splitter (to avoid getting multiple EVPCs in the system)
|
// Used for the splitter (to avoid getting multiple EVPCs in the system)
|
||||||
|
@ -38,6 +38,7 @@ public:
|
|||||||
virtual void msast_in(int state) { }
|
virtual void msast_in(int state) { }
|
||||||
virtual void clock_in(int state) { }
|
virtual void clock_in(int state) { }
|
||||||
virtual void reset_in(int state) { }
|
virtual void reset_in(int state) { }
|
||||||
|
virtual void sbe(int state) { }
|
||||||
|
|
||||||
void set_ioport(ioport_device* ioport) { m_ioport = ioport; }
|
void set_ioport(ioport_device* ioport) { m_ioport = ioport; }
|
||||||
|
|
||||||
@ -80,6 +81,7 @@ public:
|
|||||||
void msast_in(int state);
|
void msast_in(int state);
|
||||||
void clock_in(int state);
|
void clock_in(int state);
|
||||||
void reset_in(int state);
|
void reset_in(int state);
|
||||||
|
void sbe(int state);
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
auto extint_cb() { return m_console_extint.bind(); }
|
auto extint_cb() { return m_console_extint.bind(); }
|
||||||
|
@ -192,7 +192,7 @@ CRUCLK* 51||52 DBIN
|
|||||||
#include "evpc.h"
|
#include "evpc.h"
|
||||||
#include "hsgpl.h"
|
#include "hsgpl.h"
|
||||||
#include "ti_rs232.h"
|
#include "ti_rs232.h"
|
||||||
#include "spchsyn.h"
|
#include "speechadapter.h"
|
||||||
#include "memex.h"
|
#include "memex.h"
|
||||||
#include "horizon.h"
|
#include "horizon.h"
|
||||||
#include "forti.h"
|
#include "forti.h"
|
||||||
@ -484,7 +484,7 @@ void peribox_device::device_config_complete()
|
|||||||
void peribox_common_slots(device_slot_interface &device)
|
void peribox_common_slots(device_slot_interface &device)
|
||||||
{
|
{
|
||||||
device.option_add("tirs232", TI99_RS232);
|
device.option_add("tirs232", TI99_RS232);
|
||||||
device.option_add("speech", TI99_SPEECH);
|
device.option_add("speechadapter", TI99_SPEECHADAPTER);
|
||||||
device.option_add("horizon", TI99_HORIZON);
|
device.option_add("horizon", TI99_HORIZON);
|
||||||
device.option_add("ide", TI99_IDE);
|
device.option_add("ide", TI99_IDE);
|
||||||
device.option_add("usbsm", TI99_USBSM);
|
device.option_add("usbsm", TI99_USBSM);
|
||||||
|
@ -1,188 +0,0 @@
|
|||||||
// license:LGPL-2.1+
|
|
||||||
// copyright-holders:Michael Zapf
|
|
||||||
/****************************************************************************
|
|
||||||
|
|
||||||
TI-99 Speech synthesizer
|
|
||||||
|
|
||||||
We emulate the Speech Synthesizer plugged onto a P-Box adapter. The original
|
|
||||||
Speech Synthesizer device was provided as a box to be plugged into the
|
|
||||||
right side of the console. In order to be used with Geneve and SGCPU, the
|
|
||||||
speech synthesizer must be moved into the Peripheral Box.
|
|
||||||
|
|
||||||
The Speech Synthesizer used for the TI was the CD2501E, AKA TMS5200,
|
|
||||||
(internal name TMC0285), a predecessor of the TMS5220 which was used in
|
|
||||||
other commercial products.
|
|
||||||
|
|
||||||
Note that this adapter also contains the speech roms.
|
|
||||||
|
|
||||||
Michael Zapf
|
|
||||||
|
|
||||||
February 2012: Rewritten as class
|
|
||||||
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include "emu.h"
|
|
||||||
#include "spchsyn.h"
|
|
||||||
|
|
||||||
#include "speaker.h"
|
|
||||||
|
|
||||||
#define LOG_WARN (1U << 1) // Warnings
|
|
||||||
#define LOG_CONFIG (1U << 2)
|
|
||||||
#define LOG_MEM (1U << 3)
|
|
||||||
#define LOG_ADDR (1U << 4)
|
|
||||||
#define LOG_READY (1U << 5)
|
|
||||||
|
|
||||||
#define VERBOSE (LOG_CONFIG | LOG_WARN)
|
|
||||||
#include "logmacro.h"
|
|
||||||
|
|
||||||
DEFINE_DEVICE_TYPE(TI99_SPEECH, bus::ti99::peb::ti_speech_synthesizer_device, "ti99_speech", "TI-99 Speech synthesizer (on adapter card)")
|
|
||||||
|
|
||||||
namespace bus::ti99::peb {
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
ti_speech_synthesizer_device::ti_speech_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
|
||||||
device_t(mconfig, TI99_SPEECH, tag, owner, clock),
|
|
||||||
device_ti99_peribox_card_interface(mconfig, *this),
|
|
||||||
m_vsp(*this, "vsp"),
|
|
||||||
m_reading(false),
|
|
||||||
m_sbe(false),
|
|
||||||
m_dec_high(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Memory read
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ti_speech_synthesizer_device::readz(offs_t offset, uint8_t *value)
|
|
||||||
{
|
|
||||||
if (machine().side_effects_disabled()) return;
|
|
||||||
|
|
||||||
if (m_sbe)
|
|
||||||
{
|
|
||||||
*value = m_vsp->status_r() & 0xff;
|
|
||||||
LOGMASKED(LOG_MEM, "read value = %02x\n", *value);
|
|
||||||
// We should clear the lines at this point. The TI-99/4A clears the
|
|
||||||
// lines by setting the address bus to a different value, but the
|
|
||||||
// Geneve may behave differently. This may not 100% reflect the real
|
|
||||||
// situation, but it ensures a safe processing.
|
|
||||||
m_vsp->combined_rsq_wsq_w(~0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Memory write
|
|
||||||
*/
|
|
||||||
void ti_speech_synthesizer_device::write(offs_t offset, uint8_t data)
|
|
||||||
{
|
|
||||||
if (machine().side_effects_disabled()) return;
|
|
||||||
|
|
||||||
if (m_sbe)
|
|
||||||
{
|
|
||||||
LOGMASKED(LOG_MEM, "write value = %02x\n", data);
|
|
||||||
m_vsp->data_w(data);
|
|
||||||
// Note that we must NOT clear the lines here. Find the lines in the
|
|
||||||
// READY callback below.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ti_speech_synthesizer_device::setaddress_dbin(offs_t offset, int state)
|
|
||||||
{
|
|
||||||
// 1001 00xx xxxx xxx0 DBIN=1
|
|
||||||
// 1001 01xx xxxx xxx0 DBIN=0
|
|
||||||
// 1111 1000 0000 0001 mask
|
|
||||||
m_reading = (state==ASSERT_LINE);
|
|
||||||
|
|
||||||
bool valid = (((offset & 0x0400)==0) == m_reading);
|
|
||||||
|
|
||||||
if (m_dec_high)
|
|
||||||
m_sbe = ((offset & 0x7f801)==0x79000) && valid;
|
|
||||||
else
|
|
||||||
m_sbe = ((offset & 0x0f801)==0x09000) && valid;
|
|
||||||
|
|
||||||
if (m_sbe)
|
|
||||||
{
|
|
||||||
LOGMASKED(LOG_ADDR, "set address = %04x, dbin = %d\n", offset, state);
|
|
||||||
|
|
||||||
// Caution: In the current tms5220 emulation, care must be taken
|
|
||||||
// to clear one line before asserting the other line, or otherwise
|
|
||||||
// both RS* and WS* are active, which is illegal.
|
|
||||||
// Alternatively, we'll use the combined settings method
|
|
||||||
|
|
||||||
m_vsp->combined_rsq_wsq_w(m_reading ? ~tms5220_device::RS : ~tms5220_device::WS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// If other address, turn off RS* and WS* (negative logic!)
|
|
||||||
m_vsp->combined_rsq_wsq_w(~0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
void ti_speech_synthesizer_device::speech_ready(int state)
|
|
||||||
{
|
|
||||||
// The TMS5200 implementation uses true/false, not ASSERT/CLEAR semantics
|
|
||||||
// and we have to adapt a /READY to a READY line.
|
|
||||||
// The real synthesizer board uses a transistor for that purpose.
|
|
||||||
m_slot->set_ready((state==0)? ASSERT_LINE : CLEAR_LINE);
|
|
||||||
LOGMASKED(LOG_READY, "READY = %d\n", (state==0));
|
|
||||||
|
|
||||||
if ((state==0) && !m_reading)
|
|
||||||
// Clear the lines only when we are done with writing.
|
|
||||||
m_vsp->combined_rsq_wsq_w(~0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ti_speech_synthesizer_device::device_start()
|
|
||||||
{
|
|
||||||
save_item(NAME(m_reading));
|
|
||||||
save_item(NAME(m_sbe));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ti_speech_synthesizer_device::device_reset()
|
|
||||||
{
|
|
||||||
m_reading = false;
|
|
||||||
m_sbe = false;
|
|
||||||
m_dec_high = (ioport("AMADECODE")->read()!=0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ROM_START( ti99_speech )
|
|
||||||
ROM_REGION(0x8000, "vsm", 0)
|
|
||||||
ROM_LOAD("cd2325a.u2a", 0x0000, 0x4000, CRC(1f58b571) SHA1(0ef4f178716b575a1c0c970c56af8a8d97561ffe)) // at location u2, bottom of stack
|
|
||||||
ROM_LOAD("cd2326a.u2b", 0x4000, 0x4000, CRC(65d00401) SHA1(a367242c2c96cebf0e2bf21862f3f6734b2b3020)) // at location u2, top of stack
|
|
||||||
ROM_END
|
|
||||||
|
|
||||||
void ti_speech_synthesizer_device::device_add_mconfig(machine_config& config)
|
|
||||||
{
|
|
||||||
SPEAKER(config, "speech_out").front_center();
|
|
||||||
CD2501E(config, m_vsp, 640000L);
|
|
||||||
|
|
||||||
m_vsp->ready_cb().set(FUNC(ti_speech_synthesizer_device::speech_ready));
|
|
||||||
m_vsp->add_route(ALL_OUTPUTS, "speech_out", 0.50);
|
|
||||||
|
|
||||||
TMS6100(config, "vsm", 0);
|
|
||||||
m_vsp->m0_cb().set("vsm", FUNC(tms6100_device::m0_w));
|
|
||||||
m_vsp->m1_cb().set("vsm", FUNC(tms6100_device::m1_w));
|
|
||||||
m_vsp->addr_cb().set("vsm", FUNC(tms6100_device::add_w));
|
|
||||||
m_vsp->data_cb().set("vsm", FUNC(tms6100_device::data_line_r));
|
|
||||||
m_vsp->romclk_cb().set("vsm", FUNC(tms6100_device::clk_w));
|
|
||||||
}
|
|
||||||
|
|
||||||
INPUT_PORTS_START( ti99_speech )
|
|
||||||
PORT_START( "AMADECODE" )
|
|
||||||
PORT_CONFNAME( 0x01, 0x01, "Decode AMA/AMB/AMC lines" )
|
|
||||||
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
|
|
||||||
PORT_CONFSETTING( 0x01, DEF_STR( On ))
|
|
||||||
INPUT_PORTS_END
|
|
||||||
|
|
||||||
ioport_constructor ti_speech_synthesizer_device::device_input_ports() const
|
|
||||||
{
|
|
||||||
return INPUT_PORTS_NAME(ti99_speech);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tiny_rom_entry *ti_speech_synthesizer_device::device_rom_region() const
|
|
||||||
{
|
|
||||||
return ROM_NAME( ti99_speech );
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace bus::ti99::peb
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
// license:LGPL-2.1+
|
|
||||||
// copyright-holders:Michael Zapf
|
|
||||||
/****************************************************************************
|
|
||||||
|
|
||||||
TI-99 Speech Synthesizer
|
|
||||||
See spchsyn.c for documentation
|
|
||||||
|
|
||||||
Michael Zapf, October 2010
|
|
||||||
February 2012: Rewritten as class
|
|
||||||
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef MAME_BUS_TI99_PEB_SPCHSYN_H
|
|
||||||
#define MAME_BUS_TI99_PEB_SPCHSYN_H
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "peribox.h"
|
|
||||||
#include "sound/tms5220.h"
|
|
||||||
#include "machine/tms6100.h"
|
|
||||||
|
|
||||||
namespace bus::ti99::peb {
|
|
||||||
|
|
||||||
class ti_speech_synthesizer_device : public device_t, public device_ti99_peribox_card_interface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ti_speech_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
|
||||||
void readz(offs_t offset, uint8_t *value) override;
|
|
||||||
void write(offs_t offset, uint8_t data) override;
|
|
||||||
void setaddress_dbin(offs_t offset, int state) override;
|
|
||||||
|
|
||||||
void crureadz(offs_t offset, uint8_t *value) override { }
|
|
||||||
void cruwrite(offs_t offset, uint8_t data) override { }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void device_start() override;
|
|
||||||
virtual void device_reset() override;
|
|
||||||
virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
|
|
||||||
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
|
|
||||||
virtual ioport_constructor device_input_ports() const override ATTR_COLD;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void speech_ready(int state);
|
|
||||||
|
|
||||||
required_device<cd2501e_device> m_vsp;
|
|
||||||
bool m_reading;
|
|
||||||
bool m_sbe; // Signal "Speech block enable"
|
|
||||||
bool m_dec_high; // Decode the AMA/AMB/ABC address lines
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace bus::ti99::peb
|
|
||||||
|
|
||||||
DECLARE_DEVICE_TYPE_NS(TI99_SPEECH, bus::ti99::peb, ti_speech_synthesizer_device)
|
|
||||||
|
|
||||||
#endif // MAME_BUS_TI99_PEB_SPCHSYN_H
|
|
158
src/devices/bus/ti99/peb/speechadapter.cpp
Normal file
158
src/devices/bus/ti99/peb/speechadapter.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// license:LGPL-2.1+
|
||||||
|
// copyright-holders:Michael Zapf
|
||||||
|
/****************************************************************************
|
||||||
|
|
||||||
|
TI-99 Speech synthesizer adapter device
|
||||||
|
|
||||||
|
This adapter card made the sidecar Speech Synthesizer unit available to
|
||||||
|
systems without a TI-99/4A console, like the SGCPU and the Geneve. The
|
||||||
|
board must be removed from the sidecar unit and plugged on this simple
|
||||||
|
adapter board, which is then put in a slot of the Peripheral Expansion Box.
|
||||||
|
|
||||||
|
+-------+
|
||||||
|
+-----|-------|---+
|
||||||
|
| Speech syn |
|
||||||
|
| board |
|
||||||
|
| _________ |
|
||||||
|
+-----+++++++++---+
|
||||||
|
+----------------------------+|||||||+------------+
|
||||||
|
| ------- |
|
||||||
|
| Adapter board |
|
||||||
|
| |
|
||||||
|
(((o LED PEB slot connector |
|
||||||
|
+--------------|||||||||||||||||||||||||----------+
|
||||||
|
|||||||||||||||||||||||||
|
||||||
|
|
||||||
|
Technical detail:
|
||||||
|
|
||||||
|
The SBE signal (Speech Block Enable), which is generated in the TI console,
|
||||||
|
is not forwarded to the PEB. One of the tasks of this board is thus to
|
||||||
|
decode the mapped addresses once more and to activate the synthesizer
|
||||||
|
accordingly.
|
||||||
|
|
||||||
|
A second issue for Geneve users is that the address extension bits (AMA,
|
||||||
|
AMB, AMC) need to be decoded as well to avoid the synthesizer interfering
|
||||||
|
with other memory access. This can be activated in the configuration. The
|
||||||
|
default is on.
|
||||||
|
|
||||||
|
Michael Zapf
|
||||||
|
March 2025
|
||||||
|
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "speechadapter.h"
|
||||||
|
|
||||||
|
#include "speaker.h"
|
||||||
|
#include "bus/ti99/sidecar/speechsyn.h"
|
||||||
|
|
||||||
|
#define LOG_WARN (1U << 1) // Warnings
|
||||||
|
#define LOG_CONFIG (1U << 2)
|
||||||
|
#define LOG_MEM (1U << 3)
|
||||||
|
#define LOG_ADDR (1U << 4)
|
||||||
|
#define LOG_READY (1U << 5)
|
||||||
|
|
||||||
|
#define VERBOSE (LOG_CONFIG | LOG_WARN)
|
||||||
|
#include "logmacro.h"
|
||||||
|
|
||||||
|
DEFINE_DEVICE_TYPE(TI99_SPEECHADAPTER, bus::ti99::peb::ti_speechsyn_adapter_device, "ti99_speechconn", "TI-99 Speech synthesizer adapter card")
|
||||||
|
|
||||||
|
namespace bus::ti99::peb {
|
||||||
|
|
||||||
|
#define PORT "conn"
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
ti_speechsyn_adapter_device::ti_speechsyn_adapter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||||
|
device_t(mconfig, TI99_SPEECHADAPTER, tag, owner, clock),
|
||||||
|
device_ti99_peribox_card_interface(mconfig, *this),
|
||||||
|
m_port(*this, PORT),
|
||||||
|
m_dec_high(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speechsyn_adapter_device::readz(offs_t offset, uint8_t *value)
|
||||||
|
{
|
||||||
|
if (m_port != nullptr)
|
||||||
|
{
|
||||||
|
LOGMASKED(LOG_MEM, "read %06x\n", offset);
|
||||||
|
m_port->readz(offset, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speechsyn_adapter_device::write(offs_t offset, uint8_t data)
|
||||||
|
{
|
||||||
|
if (m_port != nullptr)
|
||||||
|
{
|
||||||
|
LOGMASKED(LOG_MEM, "write %06x\n", offset);
|
||||||
|
m_port->write(offset, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speechsyn_adapter_device::setaddress_dbin(offs_t offset, int state)
|
||||||
|
{
|
||||||
|
// Valid access = not(DBIN and A5)
|
||||||
|
bool reading = (state==ASSERT_LINE);
|
||||||
|
|
||||||
|
// An access is valid when reading from 9000 and writing to 9400.
|
||||||
|
bool valid = (((offset & 0x0400)==0) == reading);
|
||||||
|
bool sbe = false;
|
||||||
|
|
||||||
|
// Recreate the SBE signal that is only available at the I/O port of the console
|
||||||
|
if (m_dec_high)
|
||||||
|
// We need to decode the AMA/AMB/AMC address extension lines
|
||||||
|
sbe = ((offset & 0x7f801)==0x79000) && valid;
|
||||||
|
else
|
||||||
|
// No need to decode the extension lines
|
||||||
|
sbe = ((offset & 0x0f801)==0x09000) && valid;
|
||||||
|
|
||||||
|
if (sbe) LOGMASKED(LOG_ADDR, "set address = %04x, dbin = %d\n", offset, state);
|
||||||
|
|
||||||
|
if (m_port != nullptr)
|
||||||
|
{
|
||||||
|
m_port->sbe(sbe);
|
||||||
|
m_port->setaddress_dbin(offset, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speechsyn_adapter_device::ready(int state)
|
||||||
|
{
|
||||||
|
LOGMASKED(LOG_READY, "Incoming READY=%d from synthesizer %d\n", state);
|
||||||
|
m_slot->set_ready(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speechsyn_adapter_device::device_start()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speechsyn_adapter_device::device_reset()
|
||||||
|
{
|
||||||
|
m_dec_high = (ioport("AMADECODE")->read()!=0);
|
||||||
|
LOGMASKED(LOG_CONFIG, "Speech adapter%s decoding the AMA/B/C lines.\n", m_dec_high? "" : " not");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speechsyn_adapter_options(device_slot_interface &device)
|
||||||
|
{
|
||||||
|
device.option_add("speechsyn", TI99_SPEECHSYN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speechsyn_adapter_device::device_add_mconfig(machine_config& config)
|
||||||
|
{
|
||||||
|
TI99_IOPORT(config, m_port, 0, ti_speechsyn_adapter_options, "speechsyn");
|
||||||
|
m_port->ready_cb().set(FUNC(ti_speechsyn_adapter_device::ready));
|
||||||
|
}
|
||||||
|
|
||||||
|
INPUT_PORTS_START( ti99_speechadapter )
|
||||||
|
PORT_START( "AMADECODE" )
|
||||||
|
PORT_CONFNAME( 0x01, 0x01, "Decode AMA/AMB/AMC lines" )
|
||||||
|
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
|
||||||
|
PORT_CONFSETTING( 0x01, DEF_STR( On ))
|
||||||
|
INPUT_PORTS_END
|
||||||
|
|
||||||
|
ioport_constructor ti_speechsyn_adapter_device::device_input_ports() const
|
||||||
|
{
|
||||||
|
return INPUT_PORTS_NAME(ti99_speechadapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace bus::ti99::peb
|
||||||
|
|
49
src/devices/bus/ti99/peb/speechadapter.h
Normal file
49
src/devices/bus/ti99/peb/speechadapter.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// license:LGPL-2.1+
|
||||||
|
// copyright-holders:Michael Zapf
|
||||||
|
/****************************************************************************
|
||||||
|
|
||||||
|
TI-99 Speech Synthesizer connector adapter
|
||||||
|
for the Peripheral Expansion Box
|
||||||
|
|
||||||
|
Michael Zapf, March 2025
|
||||||
|
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAME_BUS_TI99_PEB_SPCHADPT_H
|
||||||
|
#define MAME_BUS_TI99_PEB_SPCHADPT_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "peribox.h"
|
||||||
|
#include "bus/ti99/internal/ioport.h"
|
||||||
|
|
||||||
|
namespace bus::ti99::peb {
|
||||||
|
|
||||||
|
class ti_speechsyn_adapter_device : public device_t, public device_ti99_peribox_card_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ti_speechsyn_adapter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
void readz(offs_t offset, uint8_t *value) override;
|
||||||
|
void write(offs_t offset, uint8_t data) override;
|
||||||
|
void setaddress_dbin(offs_t offset, int state) override;
|
||||||
|
void crureadz(offs_t offset, uint8_t *value) override { }
|
||||||
|
void cruwrite(offs_t offset, uint8_t data) override { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void device_start() override;
|
||||||
|
virtual void device_reset() override;
|
||||||
|
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
|
||||||
|
virtual ioport_constructor device_input_ports() const override ATTR_COLD;
|
||||||
|
|
||||||
|
private:
|
||||||
|
required_device<bus::ti99::internal::ioport_device> m_port;
|
||||||
|
bool m_dec_high;
|
||||||
|
|
||||||
|
void ready(int state);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace bus::ti99::peb
|
||||||
|
|
||||||
|
DECLARE_DEVICE_TYPE_NS(TI99_SPEECHADAPTER, bus::ti99::peb, ti_speechsyn_adapter_device)
|
||||||
|
|
||||||
|
#endif // MAME_BUS_TI99_PEB_SPCHADPT_H
|
273
src/devices/bus/ti99/sidecar/speechsyn.cpp
Normal file
273
src/devices/bus/ti99/sidecar/speechsyn.cpp
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
// license:LGPL-2.1+
|
||||||
|
// copyright-holders:Michael Zapf
|
||||||
|
/****************************************************************************
|
||||||
|
|
||||||
|
TI-99 Speech synthesizer
|
||||||
|
|
||||||
|
This is the emulation Speech Synthesizer, which plugs into the I/O port of
|
||||||
|
the TI console. Even though the sidecar expansion concept was largely
|
||||||
|
abandoned by the introduction of the Peripheral Expansion Box with the 4A,
|
||||||
|
the Speech Synthesizer was sold as a sidecar expansion until the end.
|
||||||
|
|
||||||
|
Typical setup:
|
||||||
|
Speech Synthesizer
|
||||||
|
sidecar
|
||||||
|
v
|
||||||
|
+----------------+---+----------
|
||||||
|
| TI-99/4(A) | | PEB connection cable
|
||||||
|
+------------+---+ +----------
|
||||||
|
| oooooooooo | |---+
|
||||||
|
| oooooooooo | |
|
||||||
|
+-----------------
|
||||||
|
|
||||||
|
Also as a common modification, users removed the board inside the sidecar
|
||||||
|
and placed it on an adapter to go into the PEB and thus to become
|
||||||
|
available for the Geneve or SGCPU. See bus/ti99/peb/speechadapter.cpp.
|
||||||
|
|
||||||
|
The sidecar offers a flippable lid where vocabulary expansion modules were
|
||||||
|
supposed to be plugged in, but those have never seen daylight. In most of
|
||||||
|
the units, including mine, no connector can be found under the lid, so the
|
||||||
|
decision to drop this idea must have come early.
|
||||||
|
|
||||||
|
Technical details:
|
||||||
|
|
||||||
|
The Voice Synthesis Processor (VSP) used for the TI Speech Synthesizer
|
||||||
|
is the CD2501E, aka TMS5200 (internal name TMC0285), a predecessor of the
|
||||||
|
TMS5220 which was used in many other commercial products.
|
||||||
|
Two TMS6100 circuits hold the standard vocabulary, mainly used from Extended
|
||||||
|
Basic programs.
|
||||||
|
|
||||||
|
The interaction with the TMS5200 relies completely on the READY*
|
||||||
|
line; the INT* line is not connected.
|
||||||
|
|
||||||
|
The VSP delivers a READY* signal, which needs to be inverted for the rest
|
||||||
|
of the TI system. The board of the Speech Synthesizer uses a simple
|
||||||
|
transistor for this purpose.
|
||||||
|
|
||||||
|
Michael Zapf
|
||||||
|
March 2025
|
||||||
|
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "speechsyn.h"
|
||||||
|
#include "speaker.h"
|
||||||
|
|
||||||
|
#define LOG_WARN (1U << 1) // Warnings
|
||||||
|
#define LOG_CONFIG (1U << 2)
|
||||||
|
#define LOG_MEM (1U << 3)
|
||||||
|
#define LOG_ADDR (1U << 4)
|
||||||
|
#define LOG_READY (1U << 5)
|
||||||
|
|
||||||
|
#define VERBOSE (LOG_GENERAL | LOG_WARN)
|
||||||
|
|
||||||
|
#include "logmacro.h"
|
||||||
|
|
||||||
|
DEFINE_DEVICE_TYPE(TI99_SPEECHSYN, bus::ti99::sidecar::ti_speech_synthesizer_device, "ti99_speech", "TI-99 Speech Synthesizer")
|
||||||
|
|
||||||
|
namespace bus::ti99::sidecar {
|
||||||
|
|
||||||
|
#define VSP "tms5200"
|
||||||
|
#define PORT "extport"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Constructor called from subclasses.
|
||||||
|
*/
|
||||||
|
ti_speech_synthesizer_device::ti_speech_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||||
|
: bus::ti99::internal::ioport_attached_device(mconfig, TI99_SPEECHSYN, tag, owner, clock),
|
||||||
|
m_vsp(*this, VSP),
|
||||||
|
m_port(*this, PORT),
|
||||||
|
m_reading(false),
|
||||||
|
m_sbe(CLEAR_LINE),
|
||||||
|
m_ext_ready(ASSERT_LINE),
|
||||||
|
m_ssyn_ready(ASSERT_LINE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Memory read
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::readz(offs_t offset, uint8_t *value)
|
||||||
|
{
|
||||||
|
if (m_sbe)
|
||||||
|
{
|
||||||
|
if (machine().side_effects_disabled()) return;
|
||||||
|
|
||||||
|
*value = m_vsp->status_r() & 0xff;
|
||||||
|
LOGMASKED(LOG_MEM, "read value = %02x\n", *value);
|
||||||
|
// We should clear the lines at this point. The TI-99/4A clears the
|
||||||
|
// lines by setting the address bus to a different value, but the
|
||||||
|
// Geneve may behave differently. This may not 100% reflect the real
|
||||||
|
// situation, but it ensures a safe processing.
|
||||||
|
m_vsp->combined_rsq_wsq_w(~0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass through to the external port
|
||||||
|
if (m_port != nullptr)
|
||||||
|
m_port->readz(offset, value);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Memory write
|
||||||
|
*/
|
||||||
|
void ti_speech_synthesizer_device::write(offs_t offset, uint8_t data)
|
||||||
|
{
|
||||||
|
if (m_sbe)
|
||||||
|
{
|
||||||
|
if (machine().side_effects_disabled()) return;
|
||||||
|
LOGMASKED(LOG_MEM, "write value = %02x\n", data);
|
||||||
|
m_vsp->data_w(data);
|
||||||
|
// Note that we must NOT clear the lines here. Find the lines in the
|
||||||
|
// READY callback below.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass through to the external port
|
||||||
|
if (m_port != nullptr)
|
||||||
|
m_port->write(offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::setaddress_dbin(offs_t offset, int state)
|
||||||
|
{
|
||||||
|
if (m_sbe)
|
||||||
|
{
|
||||||
|
m_reading = (state==ASSERT_LINE);
|
||||||
|
LOGMASKED(LOG_ADDR, "set address = %04x, dbin = %d\n", offset, state);
|
||||||
|
|
||||||
|
// Caution: In the current tms5220 emulation, care must be taken
|
||||||
|
// to clear one line before asserting the other line, or otherwise
|
||||||
|
// both RS* and WS* are active, which is illegal.
|
||||||
|
// Alternatively, we'll use the combined settings method
|
||||||
|
|
||||||
|
m_vsp->combined_rsq_wsq_w(m_reading ? ~tms5220_device::RS : ~tms5220_device::WS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If other address, turn off RS* and WS* (negative logic!)
|
||||||
|
m_vsp->combined_rsq_wsq_w(~0);
|
||||||
|
|
||||||
|
// Pass through to the external port
|
||||||
|
if (m_port != nullptr)
|
||||||
|
m_port->setaddress_dbin(offset, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::sbe(int state)
|
||||||
|
{
|
||||||
|
m_sbe = (state==ASSERT_LINE);
|
||||||
|
// Not forwarded to the external port
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::crureadz(offs_t offset, uint8_t *value)
|
||||||
|
{
|
||||||
|
// Pass through to the external port
|
||||||
|
if (m_port != nullptr)
|
||||||
|
m_port->crureadz(offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::cruwrite(offs_t offset, uint8_t data)
|
||||||
|
{
|
||||||
|
// Pass through to the external port
|
||||||
|
if (m_port != nullptr)
|
||||||
|
m_port->cruwrite(offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::memen_in(int state)
|
||||||
|
{
|
||||||
|
// Pass through to the external port
|
||||||
|
if (m_port != nullptr)
|
||||||
|
m_port->memen_in(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::msast_in(int state)
|
||||||
|
{
|
||||||
|
// Pass through to the external port
|
||||||
|
if (m_port != nullptr)
|
||||||
|
m_port->msast_in(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::clock_in(int state)
|
||||||
|
{
|
||||||
|
// Pass through to the external port
|
||||||
|
if (m_port != nullptr)
|
||||||
|
m_port->clock_in(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::reset_in(int state)
|
||||||
|
{
|
||||||
|
// Pass through to the external port
|
||||||
|
if (m_port != nullptr)
|
||||||
|
m_port->reset_in(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Forward the incoming interrupt to the console
|
||||||
|
*/
|
||||||
|
void ti_speech_synthesizer_device::extint(int state)
|
||||||
|
{
|
||||||
|
set_extint(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::extready(int state)
|
||||||
|
{
|
||||||
|
LOGMASKED(LOG_READY, "Incoming READY=%d from external port\n", state);
|
||||||
|
m_ext_ready = (line_state)state;
|
||||||
|
set_ready(m_ext_ready & m_ssyn_ready);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::speech_ready(int state)
|
||||||
|
{
|
||||||
|
// Invert the READY* signal
|
||||||
|
m_ssyn_ready = (state==0)? ASSERT_LINE : CLEAR_LINE;
|
||||||
|
LOGMASKED(LOG_READY, "SSyn READY = %d\n", (state==0));
|
||||||
|
|
||||||
|
if ((state==0) && !m_reading)
|
||||||
|
// Clear the lines only when we are done with writing.
|
||||||
|
m_vsp->combined_rsq_wsq_w(~0);
|
||||||
|
|
||||||
|
set_ready(m_ext_ready & m_ssyn_ready);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::device_start()
|
||||||
|
{
|
||||||
|
save_item(NAME(m_reading));
|
||||||
|
save_item(NAME(m_sbe));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::device_reset()
|
||||||
|
{
|
||||||
|
m_reading = false;
|
||||||
|
m_sbe = CLEAR_LINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ROM_START( ti99_speech )
|
||||||
|
ROM_REGION(0x8000, "vsm", 0)
|
||||||
|
ROM_LOAD("cd2325a.u2a", 0x0000, 0x4000, CRC(1f58b571) SHA1(0ef4f178716b575a1c0c970c56af8a8d97561ffe)) // at location u2, bottom of stack
|
||||||
|
ROM_LOAD("cd2326a.u2b", 0x4000, 0x4000, CRC(65d00401) SHA1(a367242c2c96cebf0e2bf21862f3f6734b2b3020)) // at location u2, top of stack
|
||||||
|
ROM_END
|
||||||
|
|
||||||
|
void ti_speech_synthesizer_device::device_add_mconfig(machine_config& config)
|
||||||
|
{
|
||||||
|
SPEAKER(config, "speech_out").front_center();
|
||||||
|
CD2501E(config, m_vsp, 640000L);
|
||||||
|
|
||||||
|
m_vsp->ready_cb().set(FUNC(ti_speech_synthesizer_device::speech_ready));
|
||||||
|
m_vsp->add_route(ALL_OUTPUTS, "speech_out", 0.50);
|
||||||
|
|
||||||
|
TMS6100(config, "vsm", 0);
|
||||||
|
m_vsp->m0_cb().set("vsm", FUNC(tms6100_device::m0_w));
|
||||||
|
m_vsp->m1_cb().set("vsm", FUNC(tms6100_device::m1_w));
|
||||||
|
m_vsp->addr_cb().set("vsm", FUNC(tms6100_device::add_w));
|
||||||
|
m_vsp->data_cb().set("vsm", FUNC(tms6100_device::data_line_r));
|
||||||
|
m_vsp->romclk_cb().set("vsm", FUNC(tms6100_device::clk_w));
|
||||||
|
|
||||||
|
TI99_IOPORT(config, m_port, 0, ti99_ioport_options_evpc1, nullptr);
|
||||||
|
m_port->extint_cb().set(FUNC(ti_speech_synthesizer_device::extint));
|
||||||
|
m_port->ready_cb().set(FUNC(ti_speech_synthesizer_device::extready));
|
||||||
|
}
|
||||||
|
|
||||||
|
const tiny_rom_entry *ti_speech_synthesizer_device::device_rom_region() const
|
||||||
|
{
|
||||||
|
return ROM_NAME( ti99_speech );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace bus::ti99::sidecar
|
65
src/devices/bus/ti99/sidecar/speechsyn.h
Normal file
65
src/devices/bus/ti99/sidecar/speechsyn.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// license:LGPL-2.1+
|
||||||
|
// copyright-holders:Michael Zapf
|
||||||
|
/****************************************************************************
|
||||||
|
|
||||||
|
Speech Synthesizer sidecar device
|
||||||
|
Michael Zapf
|
||||||
|
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAME_BUS_TI99_SIDECAR_SPEECHSYN_H
|
||||||
|
#define MAME_BUS_TI99_SIDECAR_SPEECHSYN_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "bus/ti99/internal/ioport.h"
|
||||||
|
#include "sound/tms5220.h"
|
||||||
|
#include "machine/tms6100.h"
|
||||||
|
|
||||||
|
namespace bus::ti99::sidecar {
|
||||||
|
|
||||||
|
class ti_speech_synthesizer_device : public bus::ti99::internal::ioport_attached_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ti_speech_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
void readz(offs_t offset, uint8_t *value) override;
|
||||||
|
void write(offs_t offset, uint8_t data) override;
|
||||||
|
void setaddress_dbin(offs_t offset, int state) override;
|
||||||
|
void sbe(int state) override;
|
||||||
|
|
||||||
|
void crureadz(offs_t offset, uint8_t *value) override;
|
||||||
|
void cruwrite(offs_t offset, uint8_t data) override;
|
||||||
|
|
||||||
|
void memen_in(int state) override;
|
||||||
|
void msast_in(int state) override;
|
||||||
|
|
||||||
|
void clock_in(int state) override;
|
||||||
|
void reset_in(int state) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void device_start() override ATTR_COLD;
|
||||||
|
virtual void device_reset() override ATTR_COLD;
|
||||||
|
virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
|
||||||
|
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
|
||||||
|
|
||||||
|
// Callbacks from the external port
|
||||||
|
void extint(int state);
|
||||||
|
void extready(int state);
|
||||||
|
|
||||||
|
private:
|
||||||
|
required_device<cd2501e_device> m_vsp;
|
||||||
|
required_device<bus::ti99::internal::ioport_device> m_port;
|
||||||
|
|
||||||
|
void speech_ready(int state);
|
||||||
|
|
||||||
|
bool m_reading;
|
||||||
|
bool m_sbe;
|
||||||
|
line_state m_ext_ready;
|
||||||
|
line_state m_ssyn_ready;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace bus::ti99::internal
|
||||||
|
|
||||||
|
DECLARE_DEVICE_TYPE_NS(TI99_SPEECHSYN, bus::ti99::sidecar, ti_speech_synthesizer_device)
|
||||||
|
|
||||||
|
#endif // MAME_BUS_TI99_SIDECAR_SPEECHSYN_H
|
Loading…
Reference in New Issue
Block a user