mirror of
https://github.com/holub/mame
synced 2025-04-23 17:00:53 +03:00
TMS5220/5110 merge Part 1 [Lord Nightmare]
This commit is contained in:
parent
f15f97e5d8
commit
b66574f30c
@ -46,7 +46,55 @@
|
||||
Note the standard naming for d* data bits with 7 as MSB and 0 as LSB is in lowercase.
|
||||
TI's naming has D7 as LSB and D0 as MSB and is in uppercase
|
||||
|
||||
TMS5100:
|
||||
|
||||
+-----------------+
|
||||
TST | 1 28 | CS
|
||||
PDC | 2 27 | CTL8
|
||||
ROM CK | 3 26 | ADD8
|
||||
CPU CK | 4 25 | CTL1
|
||||
VDD | 5 24 | ADD1
|
||||
CR OSC | 6 23 | CTL2
|
||||
RC OSC | 7 22 | ADD2
|
||||
T11 | 8 21 | ADD4
|
||||
NC | 9 20 | CTL4
|
||||
I/O | 10 19 | M1
|
||||
SPK1 | 11 18 | NC
|
||||
SPK2 | 12 17 | NC
|
||||
PROM OUT | 13 16 | NC
|
||||
VSS | 14 15 | M0
|
||||
+-----------------+
|
||||
|
||||
T11: Sync for serial data out
|
||||
|
||||
|
||||
M58817
|
||||
|
||||
The following connections could be derived from radar scope schematics.
|
||||
The M58817 is not 100% pin compatible to the 5100, but really close.
|
||||
|
||||
+-----------------+
|
||||
(NC) | 1 28 | CS
|
||||
PDC | 2 27 | CTL8
|
||||
ROM CK | 3 26 | ADD8 (to 58819)
|
||||
(NC) | 4 25 | CTL1
|
||||
(VDD,-5) | 5 24 | ADD1 (to 58819)
|
||||
(GND) | 6 23 | CTL2
|
||||
Xin | 7 22 | ADD2 (to 58819)
|
||||
Xout | 8 21 | ADD4 (to 58819)
|
||||
(NC) | 9 20 | CTL4
|
||||
(VDD,-5) | 10 19 | Status back to CPU
|
||||
(NC) | 11 18 | C1 (to 58819)
|
||||
SPKR | 12 17 | (NC)
|
||||
SPKR | 13 16 | C0 (to 58819)
|
||||
(NC) | 14 15 | (5V)
|
||||
+-----------------+
|
||||
|
||||
TODO:
|
||||
5110:
|
||||
* implement CS
|
||||
* TMS5110_CMD_TEST_TALK is only partially implemented
|
||||
5220:
|
||||
* Samples repeat over and over in the 'eprom' test mode. Needs investigation.
|
||||
* Implement a ready callback for pc interfaces
|
||||
- this will be quite a challenge since for it to be really accurate
|
||||
@ -272,7 +320,7 @@ static INT16 clip_analog(INT16 cliptemp);
|
||||
/* must be defined; if 0, output the waveform as if it was tapped on the speaker pin as usual, if 1, output the waveform as if it was tapped on the i/o pin (volume is much lower in the latter case) */
|
||||
#define FORCE_DIGITAL 0
|
||||
|
||||
/* must be defined; if 1, normal speech (one A cycle, one B cycle per interpolation step); if 0; speak as if SPKSLOW was used (two A cycles, one B cycle per interpolation step) */
|
||||
/* 5220 only; must be defined; if 1, normal speech (one A cycle, one B cycle per interpolation step); if 0; speak as if SPKSLOW was used (two A cycles, one B cycle per interpolation step) */
|
||||
#define FORCE_SUBC_RELOAD 1
|
||||
|
||||
|
||||
@ -280,9 +328,9 @@ static INT16 clip_analog(INT16 cliptemp);
|
||||
#undef VERBOSE
|
||||
// above is general, somewhat obsolete, catch all for debugs which don't fit elsewhere
|
||||
#undef DEBUG_DUMP_INPUT_DATA
|
||||
// above dumps the data input to the tms52xx to stdout, useful for making logged data dumps for real hardware tests
|
||||
// 5220 only; above dumps the data written to the tms52xx to stdout, useful for making logged data dumps for real hardware tests
|
||||
#undef DEBUG_FIFO
|
||||
// above debugs fifo stuff: writes, reads and flag updates
|
||||
// 5220 only; above debugs fifo stuff: writes, reads and flag updates
|
||||
#undef DEBUG_PARSE_FRAME_DUMP
|
||||
// above dumps each frame to stderr: be sure to select one of the options below if you define it!
|
||||
#undef DEBUG_PARSE_FRAME_DUMP_BIN
|
||||
@ -310,18 +358,39 @@ static INT16 clip_analog(INT16 cliptemp);
|
||||
|
||||
#define MAX_SAMPLE_CHUNK 512
|
||||
|
||||
/* Variants */
|
||||
/* 6+4 Variants, from tms5110r.inc */
|
||||
|
||||
#define TMS5220_IS_5220C (4)
|
||||
#define TMS5220_IS_5200 (5)
|
||||
#define TMS5220_IS_5220 (6)
|
||||
#define TMS5220_IS_CD2501ECD (7)
|
||||
#define TMS5220_IS_TMC0281 (1)
|
||||
#define TMS5220_IS_TMC0281D (2)
|
||||
#define TMS5220_IS_CD2801 (3)
|
||||
#define TMS5220_IS_CD2802 (4)
|
||||
#define TMS5220_IS_TMS5110A (5)
|
||||
#define TMS5220_IS_M58817 (6)
|
||||
#define TMS5220_IS_5220C (7)
|
||||
#define TMS5220_IS_5200 (8)
|
||||
#define TMS5220_IS_5220 (9)
|
||||
#define TMS5220_IS_CD2501ECD (10)
|
||||
|
||||
#define TMS5220_IS_CD2501E TMS5220_IS_5200
|
||||
|
||||
// 52xx: decide whether we have rate control or not
|
||||
#define TMS5220_HAS_RATE_CONTROL ((m_variant == TMS5220_IS_5220C) || (m_variant == TMS5220_IS_CD2501ECD))
|
||||
|
||||
// All: decide whether we are a 51xx or a 52xx
|
||||
#define TMS5220_IS_52xx ((m_variant == TMS5220_IS_5220C) || (m_variant == TMS5220_IS_5200) || (m_variant == TMS5220_IS_5220) || (m_variant == TMS5220_IS_CD2501ECD))
|
||||
|
||||
/* 51xx: States for CTL */
|
||||
// ctl bus is input to tms51xx
|
||||
#define CTL_STATE_INPUT (0)
|
||||
// ctl bus is outputting a test talk command on CTL1(bit 0)
|
||||
#define CTL_STATE_TTALK_OUTPUT (1)
|
||||
// ctl bus is switching direction, next will be above
|
||||
#define CTL_STATE_NEXT_TTALK_OUTPUT (2)
|
||||
// ctl bus is outputting a read nybble 'output' command on CTL1,2,4,8 (bits 0-3)
|
||||
#define CTL_STATE_OUTPUT (3)
|
||||
// ctl bus is switching direction, next will be above
|
||||
#define CTL_STATE_NEXT_OUTPUT (4)
|
||||
|
||||
static const UINT8 reload_table[4] = { 0, 2, 4, 6 }; //sample count reload for 5220c and cd2501ecd only; 5200 and 5220 always reload with 0; keep in mind this is loaded on IP=0 PC=12 subcycle=1 so it immediately will increment after one sample, effectively being 1,3,5,7 as in the comments above.
|
||||
|
||||
// Pull in the ROM tables
|
||||
@ -332,6 +401,24 @@ void tms5220_device::set_variant(int variant)
|
||||
{
|
||||
switch (variant)
|
||||
{
|
||||
case TMS5220_IS_TMC0281:
|
||||
m_coeff = &T0280B_0281A_coeff;
|
||||
break;
|
||||
case TMS5220_IS_TMC0281D:
|
||||
m_coeff = &T0280D_0281D_coeff;
|
||||
break;
|
||||
case TMS5220_IS_CD2801:
|
||||
m_coeff = &T0280F_2801A_coeff;
|
||||
break;
|
||||
case TMS5220_IS_M58817:
|
||||
m_coeff = &M58817_coeff;
|
||||
break;
|
||||
case TMS5220_IS_CD2802:
|
||||
m_coeff = &T0280F_2802_coeff;
|
||||
break;
|
||||
case TMS5220_IS_TMS5110A:
|
||||
m_coeff = &tms5110a_coeff;
|
||||
break;
|
||||
case TMS5220_IS_5200:
|
||||
case TMS5220_IS_CD2501ECD:
|
||||
m_coeff = &T0285_2501E_coeff;
|
||||
@ -458,7 +545,59 @@ static void printbits(long data, int num)
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_data_write -- handle a write to the TMS5220
|
||||
tms5220_device::new_int_write -- wrap a write to the VSM
|
||||
|
||||
***********************************************************************************************/
|
||||
void tms5220_device::new_int_write(UINT8 rc, UINT8 m0, UINT8 m1, UINT8 addr)
|
||||
{
|
||||
if (!m_m0_cb.isnull())
|
||||
m_m0_cb(m0);
|
||||
if (!m_m1_cb.isnull())
|
||||
m_m1_cb(m1);
|
||||
if (!m_addr_cb.isnull())
|
||||
m_addr_cb((offs_t)0, addr);
|
||||
if (!m_romclk_cb.isnull())
|
||||
{
|
||||
//printf("rc %d\n", rc);
|
||||
m_romclk_cb(rc);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_device::new_int_write_addr -- wrap a 'load address' set of writes to the VSM
|
||||
|
||||
***********************************************************************************************/
|
||||
void tms5220_device::new_int_write_addr(UINT8 addr)
|
||||
{
|
||||
new_int_write(1, 0, 1, addr); // romclk 1, m0 0, m1 1, addr bus nybble = xxxx
|
||||
new_int_write(0, 0, 1, addr); // romclk 0, m0 0, m1 1, addr bus nybble = xxxx
|
||||
new_int_write(1, 0, 0, addr); // romclk 1, m0 0, m1 0, addr bus nybble = xxxx
|
||||
new_int_write(0, 0, 0, addr); // romclk 0, m0 0, m1 0, addr bus nybble = xxxx
|
||||
}
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_device::new_int_write_addr -- wrap a 'read bit' set of writes to the VSM
|
||||
|
||||
***********************************************************************************************/
|
||||
UINT8 tms5220_device::new_int_read()
|
||||
{
|
||||
new_int_write(1, 1, 0, 0); // romclk 1, m0 1, m1 0, addr bus nybble = 0/open bus
|
||||
new_int_write(0, 1, 0, 0); // romclk 0, m0 1, m1 0, addr bus nybble = 0/open bus
|
||||
new_int_write(1, 0, 0, 0); // romclk 1, m0 0, m1 0, addr bus nybble = 0/open bus
|
||||
new_int_write(0, 0, 0, 0); // romclk 0, m0 0, m1 0, addr bus nybble = 0/open bus
|
||||
if (!m_data_cb.isnull())
|
||||
return m_data_cb();
|
||||
#ifdef VERBOSE
|
||||
logerror("WARNING: CALLBACK MISSING, RETURNING 0!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_device::data_write -- handle a write to the TMS5220
|
||||
|
||||
***********************************************************************************************/
|
||||
|
||||
@ -626,13 +765,39 @@ int tms5220_device::extract_bits(int count)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef USE_NEW_TMS6100_CODE
|
||||
/** TODO: get rid of this old code */
|
||||
// extract from VSM (speech ROM)
|
||||
if (m_speechrom)
|
||||
val = m_speechrom->read(count);
|
||||
#else
|
||||
while (count--)
|
||||
{
|
||||
val = (val << 1) | new_int_read();
|
||||
#ifdef VERBOSE
|
||||
logerror("bit read: %d\n", val&1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/** TODO: dummy reads should be auto-done for tms52xx for the first read after an address load, but not tms51xx where they need to be done manually, if needed */
|
||||
void tms5220_device::perform_dummy_read()
|
||||
{
|
||||
if (m_schedule_dummy_read)
|
||||
{
|
||||
#ifdef VERBOSE
|
||||
int data = new_int_read();
|
||||
logerror("TMS5110 performing dummy read; value read = %1i\n", data & 1);
|
||||
#else
|
||||
new_int_read();
|
||||
#endif
|
||||
m_schedule_dummy_read = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************************************
|
||||
|
||||
tms5220_status_read -- read status or data from the TMS5220
|
||||
@ -1470,9 +1635,14 @@ void tms5220_device::device_start()
|
||||
set_variant(TMS5220_IS_5220);
|
||||
m_clock = clock();
|
||||
|
||||
/* resolve irq and readyq line */
|
||||
/* resolve callbacks */
|
||||
m_irq_handler.resolve();
|
||||
m_readyq_handler.resolve();
|
||||
m_m0_cb.resolve();
|
||||
m_m1_cb.resolve();
|
||||
m_romclk_cb.resolve();
|
||||
m_addr_cb.resolve();
|
||||
m_data_cb.resolve();
|
||||
|
||||
/* initialize a stream */
|
||||
m_stream = machine().sound().stream_alloc(*this, 0, 1, clock() / 80);
|
||||
@ -1917,7 +2087,12 @@ tms5220_device::tms5220_device(const machine_config &mconfig, const char *tag, d
|
||||
device_sound_interface(mconfig, *this),
|
||||
m_irq_handler(*this),
|
||||
m_readyq_handler(*this),
|
||||
m_speechrom_tag(nullptr)
|
||||
m_speechrom_tag(nullptr),
|
||||
m_m0_cb(*this),
|
||||
m_m1_cb(*this),
|
||||
m_addr_cb(*this),
|
||||
m_data_cb(*this),
|
||||
m_romclk_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1926,7 +2101,12 @@ tms5220_device::tms5220_device(const machine_config &mconfig, device_type type,
|
||||
device_sound_interface(mconfig, *this),
|
||||
m_irq_handler(*this),
|
||||
m_readyq_handler(*this),
|
||||
m_speechrom_tag(nullptr)
|
||||
m_speechrom_tag(nullptr),
|
||||
m_m0_cb(*this),
|
||||
m_m1_cb(*this),
|
||||
m_addr_cb(*this),
|
||||
m_data_cb(*this),
|
||||
m_romclk_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -25,9 +25,25 @@
|
||||
#define MCFG_TMS52XX_READYQ_HANDLER(_devcb) \
|
||||
devcb = &tms5220_device::set_readyq_handler(*device, DEVCB_##_devcb);
|
||||
|
||||
/* old VSM handler, remove me! */
|
||||
#define MCFG_TMS52XX_SPEECHROM(_tag) \
|
||||
tms5220_device::set_speechrom_tag(*device, _tag);
|
||||
|
||||
/* new VSM handler */
|
||||
#define MCFG_TMS52XX_M0_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_m0_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TMS52XX_M1_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_m1_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TMS52XX_ADDR_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_addr_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TMS52XX_DATA_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_data_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TMS52XX_ROMCLK_CB(_devcb) \
|
||||
devcb = &tms5220_device::set_romclk_callback(*device, DEVCB_##_devcb);
|
||||
class tms5220_device : public device_t,
|
||||
public device_sound_interface
|
||||
{
|
||||
@ -38,7 +54,14 @@ public:
|
||||
// static configuration helpers
|
||||
template<class _Object> static devcb_base &set_irq_handler(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_irq_handler.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_readyq_handler(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_readyq_handler.set_callback(object); }
|
||||
// old VSM support, remove me!
|
||||
static void set_speechrom_tag(device_t &device, const char *_tag) { downcast<tms5220_device &>(device).m_speechrom_tag = _tag; }
|
||||
// new VSM support
|
||||
template<class _Object> static devcb_base &set_m0_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_m0_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_m1_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_m1_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_addr_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_addr_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_data_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_data_cb.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_romclk_callback(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_romclk_cb.set_callback(object); }
|
||||
|
||||
/* Control lines - once written to will switch interface into
|
||||
* "true" timing behaviour.
|
||||
@ -73,6 +96,12 @@ protected:
|
||||
void set_variant(int variant);
|
||||
|
||||
private:
|
||||
// 51xx and VSM related
|
||||
void new_int_write(UINT8 rc, UINT8 m0, UINT8 m1, UINT8 addr);
|
||||
void new_int_write_addr(UINT8 addr);
|
||||
UINT8 new_int_read();
|
||||
void perform_dummy_read();
|
||||
// 52xx or common
|
||||
void register_for_save_states();
|
||||
void data_write(int data);
|
||||
void update_fifo_status_and_ints();
|
||||
@ -96,6 +125,24 @@ private:
|
||||
/* coefficient tables */
|
||||
const struct tms5100_coeffs *m_coeff;
|
||||
|
||||
/* these contain global status bits */
|
||||
UINT8 m_PDC;
|
||||
UINT8 m_CTL_pins;
|
||||
UINT8 m_state;
|
||||
|
||||
/* New VSM interface */
|
||||
UINT32 m_address;
|
||||
UINT8 m_next_is_address;
|
||||
UINT8 m_schedule_dummy_read;
|
||||
UINT8 m_addr_bit;
|
||||
/* read byte */
|
||||
UINT8 m_CTL_buffer;
|
||||
|
||||
/* Old VSM interface; R Nabet : These have been added to emulate speech Roms */
|
||||
//UINT8 m_schedule_dummy_read; /* set after each load address, so that next read operation is preceded by a dummy read */
|
||||
UINT8 m_data_register; /* data register, used by read command */
|
||||
UINT8 m_RDB_flag; /* whether we should read data register or status register */
|
||||
|
||||
/* these contain data that describes the 128-bit data FIFO */
|
||||
UINT8 m_fifo[FIFO_SIZE];
|
||||
UINT8 m_fifo_head;
|
||||
@ -167,11 +214,6 @@ private:
|
||||
UINT16 m_RNG; /* the random noise generator configuration is: 1 + x + x^3 + x^4 + x^13 TODO: no it isn't */
|
||||
INT16 m_excitation_data;
|
||||
|
||||
/* R Nabet : These have been added to emulate speech Roms */
|
||||
UINT8 m_schedule_dummy_read; /* set after each load address, so that next read operation is preceded by a dummy read */
|
||||
UINT8 m_data_register; /* data register, used by read command */
|
||||
UINT8 m_RDB_flag; /* whether we should read data register or status register */
|
||||
|
||||
/* The TMS52xx has two different ways of providing output data: the
|
||||
analog speaker pin (which was usually used) and the Digital I/O pin.
|
||||
The internal DAC used to feed the analog pin is only 8 bits, and has the
|
||||
@ -201,8 +243,18 @@ private:
|
||||
/* callbacks */
|
||||
devcb_write_line m_irq_handler;
|
||||
devcb_write_line m_readyq_handler;
|
||||
// next 2 lines are old speechrom handler, remove me!
|
||||
const char *m_speechrom_tag;
|
||||
speechrom_device *m_speechrom;
|
||||
// next lines are new speechrom handler
|
||||
devcb_write_line m_m0_cb; // the M0 line
|
||||
devcb_write_line m_m1_cb; // the M1 line
|
||||
devcb_write8 m_addr_cb; // Write to ADD1,2,4,8 - 4 address bits
|
||||
devcb_read_line m_data_cb; // Read one bit from ADD8/Data - voice data
|
||||
// On a real chip rom_clk is running all the time
|
||||
// Here, we only use it to properly emulate the protocol.
|
||||
// Do not rely on it to be a timed signal.
|
||||
devcb_write_line m_romclk_cb; // rom clock - Only used to drive the data lines
|
||||
};
|
||||
|
||||
extern const device_type TMS5220;
|
||||
|
Loading…
Reference in New Issue
Block a user