mirror of
https://github.com/holub/mame
synced 2025-07-05 18:08:04 +03:00
s14001a: shorthand variable types, small cleanup
This commit is contained in:
parent
a8d909a02a
commit
d352702d22
@ -2,22 +2,20 @@
|
||||
// copyright-holders:Ed Bernard, Jonathan Gevaryahu, hap
|
||||
// thanks-to:Kevin Horton
|
||||
/*
|
||||
SSi TSI S14001A speech IC emulator
|
||||
aka CRC: Custom ROM Controller, designed in 1975, first usage in 1976 on TSI Speech+ calculator
|
||||
Originally written for MAME by Jonathan Gevaryahu(Lord Nightmare) 2006-2013,
|
||||
replaced with near-complete rewrite by Ed Bernard in 2016
|
||||
|
||||
TODO:
|
||||
- nothing at the moment?
|
||||
SSi TSI S14001A speech IC emulator
|
||||
aka CRC: Custom ROM Controller, designed in 1975, first usage in 1976 on TSI Speech+ calculator
|
||||
Originally written for MAME by Jonathan Gevaryahu(Lord Nightmare) 2006-2013,
|
||||
replaced with near-complete rewrite by Ed Bernard in 2016
|
||||
|
||||
Further reading:
|
||||
- http://www.vintagecalculators.com/html/speech-.html
|
||||
- http://www.vintagecalculators.com/html/development_of_the_tsi_speech-.html
|
||||
- http://www.vintagecalculators.com/html/speech-_state_machine.html
|
||||
- https://archive.org/stream/pdfy-QPCSwTWiFz1u9WU_/david_djvu.txt
|
||||
*/
|
||||
Further reading:
|
||||
- http://www.vintagecalculators.com/html/speech-.html
|
||||
- http://www.vintagecalculators.com/html/development_of_the_tsi_speech-.html
|
||||
- http://www.vintagecalculators.com/html/speech-_state_machine.html
|
||||
- https://archive.org/stream/pdfy-QPCSwTWiFz1u9WU_/david_djvu.txt
|
||||
|
||||
Chip Pinout:
|
||||
|
||||
/* Chip Pinout:
|
||||
The original datasheet (which is lost as far as I know) clearly called the
|
||||
s14001a chip the 'CRC chip', or 'Custom Rom Controller', as it appears with
|
||||
this name on the Stern and Canon schematics, as well as on some TSI speech
|
||||
@ -101,6 +99,7 @@ line is held high, the first address byte of the first word will be read repeate
|
||||
every clock, with the rom enable line enabled constantly (i.e. it doesn't toggle on
|
||||
and off as it normally does during speech). Once START has gone low-high-low, the
|
||||
/BUSY line will go low until 3 clocks after the chip is done speaking.
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -108,7 +107,7 @@ and off as it normally does during speech). Once START has gone low-high-low, th
|
||||
|
||||
namespace {
|
||||
|
||||
uint8_t Mux8To2(bool bVoicedP2, uint8_t uPPQtrP2, uint8_t uDeltaAdrP2, uint8_t uRomDataP2)
|
||||
u8 Mux8To2(bool bVoicedP2, u8 uPPQtrP2, u8 uDeltaAdrP2, u8 uRomDataP2)
|
||||
{
|
||||
// pick two bits of rom data as delta
|
||||
|
||||
@ -120,7 +119,7 @@ uint8_t Mux8To2(bool bVoicedP2, uint8_t uPPQtrP2, uint8_t uDeltaAdrP2, uint8_t u
|
||||
}
|
||||
|
||||
|
||||
void CalculateIncrement(bool bVoicedP2, uint8_t uPPQtrP2, bool bPPQStartP2, uint8_t uDelta, uint8_t uDeltaOldP2, uint8_t &uDeltaOldP1, uint8_t &uIncrementP2, bool &bAddP2)
|
||||
void CalculateIncrement(bool bVoicedP2, u8 uPPQtrP2, bool bPPQStartP2, u8 uDelta, u8 uDeltaOldP2, u8 &uDeltaOldP1, u8 &uIncrementP2, bool &bAddP2)
|
||||
{
|
||||
// uPPQtr, pitch period quarter counter; 2 lsb of uLength
|
||||
// bPPStart, start of a pitch period
|
||||
@ -130,7 +129,7 @@ void CalculateIncrement(bool bVoicedP2, uint8_t uPPQtrP2, bool bPPQStartP2, uint
|
||||
if ((uPPQtrP2 == 0x00) && bPPQStartP2) // note this is done for voiced and unvoiced
|
||||
uDeltaOldP2 = 0x02;
|
||||
|
||||
static constexpr uint8_t uIncrements[4][4] =
|
||||
static constexpr u8 uIncrements[4][4] =
|
||||
{
|
||||
// 00 01 10 11
|
||||
{ 3, 3, 1, 1,}, // 00
|
||||
@ -159,7 +158,7 @@ void CalculateIncrement(bool bVoicedP2, uint8_t uPPQtrP2, bool bPPQStartP2, uint
|
||||
}
|
||||
|
||||
|
||||
uint8_t CalculateOutput(bool bVoiced, bool bXSilence, uint8_t uPPQtr, bool bPPQStart, uint8_t uLOutput, uint8_t uIncrementP2, bool bAddP2)
|
||||
u8 CalculateOutput(bool bVoiced, bool bXSilence, u8 uPPQtr, bool bPPQStart, u8 uLOutput, u8 uIncrementP2, bool bAddP2)
|
||||
{
|
||||
// implemented to mimic silicon (a bit)
|
||||
// limits output to 0x00 and 0x0f
|
||||
@ -175,9 +174,9 @@ uint8_t CalculateOutput(bool bVoiced, bool bXSilence, uint8_t uPPQtr, bool bPPQS
|
||||
uLOutput = 7;
|
||||
|
||||
// adder
|
||||
uint8_t uTmp = uLOutput;
|
||||
u8 uTmp = uLOutput;
|
||||
if (!bAddP2)
|
||||
uTmp ^= 0x0F; // turns subtraction into addition
|
||||
uTmp ^= 0x0f; // turns subtraction into addition
|
||||
|
||||
// add 0, 1, 3; limit at 15
|
||||
uTmp += uIncrementP2;
|
||||
@ -185,7 +184,7 @@ uint8_t CalculateOutput(bool bVoiced, bool bXSilence, uint8_t uPPQtr, bool bPPQS
|
||||
uTmp = 15;
|
||||
|
||||
if (!bAddP2)
|
||||
uTmp ^= 0x0F; // turns addition back to subtraction
|
||||
uTmp ^= 0x0f; // turns addition back to subtraction
|
||||
|
||||
return uTmp;
|
||||
}
|
||||
@ -196,7 +195,7 @@ uint8_t CalculateOutput(bool bVoiced, bool bXSilence, uint8_t uPPQtr, bool bPPQS
|
||||
// device definition
|
||||
DEFINE_DEVICE_TYPE(S14001A, s14001a_device, "s14001a", "SSi TSI S14001A")
|
||||
|
||||
s14001a_device::s14001a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
s14001a_device::s14001a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
device_t(mconfig, S14001A, tag, owner, clock),
|
||||
device_sound_interface(mconfig, *this),
|
||||
m_SpeechRom(*this, DEVICE_SELF),
|
||||
@ -303,7 +302,7 @@ void s14001a_device::sound_stream_update(sound_stream &stream, std::vector<read_
|
||||
for (int i = 0; i < outputs[0].samples(); i++)
|
||||
{
|
||||
Clock();
|
||||
int16_t sample = m_uOutputP2 - 7; // range -7..8
|
||||
s16 sample = m_uOutputP2 - 7; // range -7..8
|
||||
outputs[0].put_int(i, sample, 8);
|
||||
}
|
||||
}
|
||||
@ -330,7 +329,7 @@ int s14001a_device::busy_r()
|
||||
return (m_bBusyP1) ? 1 : 0;
|
||||
}
|
||||
|
||||
void s14001a_device::data_w(uint8_t data)
|
||||
void s14001a_device::data_w(u8 data)
|
||||
{
|
||||
m_stream->update();
|
||||
m_uWord = data & 0x3f; // C0-C5
|
||||
@ -340,10 +339,11 @@ void s14001a_device::start_w(int state)
|
||||
{
|
||||
m_stream->update();
|
||||
m_bStart = (state != 0);
|
||||
if (m_bStart) m_uStateP1 = states::WORDWAIT;
|
||||
if (m_bStart)
|
||||
m_uStateP1 = states::WORDWAIT;
|
||||
}
|
||||
|
||||
void s14001a_device::set_clock(uint32_t clock)
|
||||
void s14001a_device::set_clock(u32 clock)
|
||||
{
|
||||
m_stream->update();
|
||||
m_stream->set_sample_rate(clock);
|
||||
@ -354,7 +354,7 @@ void s14001a_device::set_clock(uint32_t clock)
|
||||
Device emulation
|
||||
**************************************************************************/
|
||||
|
||||
uint8_t s14001a_device::readmem(uint16_t offset, bool phase)
|
||||
u8 s14001a_device::readmem(u16 offset, bool phase)
|
||||
{
|
||||
offset &= 0xfff; // 11-bit internal
|
||||
return (m_ext_read_handler.isunset()) ? m_SpeechRom[offset & (m_SpeechRom.bytes() - 1)] : m_ext_read_handler(offset);
|
||||
@ -393,10 +393,10 @@ bool s14001a_device::Clock()
|
||||
m_uRomAddrP2 = m_RomAddrP1;
|
||||
|
||||
// setup carries from phase 2 values
|
||||
m_bDAR04To00CarryP2 = m_uDAR04To00P2 == 0x1F;
|
||||
m_bPPQCarryP2 = m_bDAR04To00CarryP2 && ((m_uLengthP2&0x03) == 0x03); // pitch period quarter
|
||||
m_bRepeatCarryP2 = m_bPPQCarryP2 && ((m_uLengthP2&0x0C) == 0x0C);
|
||||
m_bLengthCarryP2 = m_bRepeatCarryP2 && ( m_uLengthP2 == 0x7F);
|
||||
m_bDAR04To00CarryP2 = m_uDAR04To00P2 == 0x1f;
|
||||
m_bPPQCarryP2 = m_bDAR04To00CarryP2 && ((m_uLengthP2 & 0x03) == 0x03); // pitch period quarter
|
||||
m_bRepeatCarryP2 = m_bPPQCarryP2 && ((m_uLengthP2 & 0x0c) == 0x0c);
|
||||
m_bLengthCarryP2 = m_bRepeatCarryP2 && ( m_uLengthP2 == 0x7f);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -407,7 +407,8 @@ bool s14001a_device::Clock()
|
||||
{
|
||||
case states::IDLE:
|
||||
m_uOutputP1 = 7;
|
||||
if (m_bStart) m_uStateP1 = states::WORDWAIT;
|
||||
if (m_bStart)
|
||||
m_uStateP1 = states::WORDWAIT;
|
||||
|
||||
if (m_bBusyP1)
|
||||
m_bsy_handler(0);
|
||||
@ -417,12 +418,12 @@ bool s14001a_device::Clock()
|
||||
case states::WORDWAIT:
|
||||
// the delta address register latches the word number into bits 03 to 08
|
||||
// all other bits forced to 0. 04 to 08 makes a multiply by two.
|
||||
m_uDAR13To05P1 = (m_uWord&0x3C)>>2;
|
||||
m_uDAR04To00P1 = (m_uWord&0x03)<<3;
|
||||
m_RomAddrP1 = (m_uDAR13To05P1<<3)|(m_uDAR04To00P1>>2); // remove lower two bits
|
||||
m_uDAR13To05P1 = (m_uWord & 0x3c) >> 2;
|
||||
m_uDAR04To00P1 = (m_uWord & 0x03) << 3;
|
||||
m_RomAddrP1 = (m_uDAR13To05P1 << 3) | (m_uDAR04To00P1 >> 2); // remove lower two bits
|
||||
|
||||
m_uOutputP1 = 7;
|
||||
if (m_bStart) m_uStateP1 = states::WORDWAIT;
|
||||
else m_uStateP1 = states::CWARMSB;
|
||||
m_uStateP1 = m_bStart ? states::WORDWAIT : states::CWARMSB;
|
||||
|
||||
if (!m_bBusyP1)
|
||||
m_bsy_handler(1);
|
||||
@ -431,59 +432,60 @@ bool s14001a_device::Clock()
|
||||
|
||||
case states::CWARMSB:
|
||||
if (m_uPrintLevel >= 1)
|
||||
printf("\n speaking word %02x",m_uWord);
|
||||
logerror("\n speaking word %02x",m_uWord);
|
||||
|
||||
// use uDAR to load uCWAR 8 msb
|
||||
m_uCWARP1 = readmem(m_uRomAddrP2,m_bPhase1)<<4; // note use of rom address setup in previous state
|
||||
m_uCWARP1 = readmem(m_uRomAddrP2, m_bPhase1) << 4; // note use of rom address setup in previous state
|
||||
// increment DAR by 4, 2 lsb's count deltas within a byte
|
||||
m_uDAR04To00P1 += 4;
|
||||
if (m_uDAR04To00P1 >= 32) m_uDAR04To00P1 = 0; // emulate 5 bit counter
|
||||
m_RomAddrP1 = (m_uDAR13To05P1<<3)|(m_uDAR04To00P1>>2); // remove lower two bits
|
||||
if (m_uDAR04To00P1 >= 32)
|
||||
m_uDAR04To00P1 = 0; // emulate 5 bit counter
|
||||
m_RomAddrP1 = (m_uDAR13To05P1 << 3) | (m_uDAR04To00P1 >> 2); // remove lower two bits
|
||||
|
||||
m_uOutputP1 = 7;
|
||||
if (m_bStart) m_uStateP1 = states::WORDWAIT;
|
||||
else m_uStateP1 = states::CWARLSB;
|
||||
m_uStateP1 = m_bStart ? states::WORDWAIT : states::CWARLSB;
|
||||
break;
|
||||
|
||||
case states::CWARLSB:
|
||||
m_uCWARP1 = m_uCWARP2|(readmem(m_uRomAddrP2,m_bPhase1)>>4); // setup in previous state
|
||||
m_uCWARP1 = m_uCWARP2 | (readmem(m_uRomAddrP2, m_bPhase1) >> 4); // setup in previous state
|
||||
m_RomAddrP1 = m_uCWARP1;
|
||||
|
||||
m_uOutputP1 = 7;
|
||||
if (m_bStart) m_uStateP1 = states::WORDWAIT;
|
||||
else m_uStateP1 = states::DARMSB;
|
||||
m_uStateP1 = m_bStart ? states::WORDWAIT : states::DARMSB;
|
||||
break;
|
||||
|
||||
case states::DARMSB:
|
||||
m_uDAR13To05P1 = readmem(m_uRomAddrP2,m_bPhase1)<<1; // 9 bit counter, 8 MSBs from ROM, lsb zeroed
|
||||
m_uDAR13To05P1 = readmem(m_uRomAddrP2, m_bPhase1) << 1; // 9 bit counter, 8 MSBs from ROM, lsb zeroed
|
||||
m_uDAR04To00P1 = 0;
|
||||
m_uCWARP1++;
|
||||
m_RomAddrP1 = m_uCWARP1;
|
||||
m_uNControlWords++; // statistics
|
||||
|
||||
m_uOutputP1 = 7;
|
||||
if (m_bStart) m_uStateP1 = states::WORDWAIT;
|
||||
else m_uStateP1 = states::CTRLBITS;
|
||||
m_uStateP1 = m_bStart ? states::WORDWAIT : states::CTRLBITS;
|
||||
break;
|
||||
|
||||
case states::CTRLBITS:
|
||||
m_bStopP1 = readmem(m_uRomAddrP2,m_bPhase1)&0x80? true: false;
|
||||
m_bVoicedP1 = readmem(m_uRomAddrP2,m_bPhase1)&0x40? true: false;
|
||||
m_bSilenceP1 = readmem(m_uRomAddrP2,m_bPhase1)&0x20? true: false;
|
||||
m_uXRepeatP1 = readmem(m_uRomAddrP2,m_bPhase1)&0x03;
|
||||
m_uLengthP1 =(readmem(m_uRomAddrP2,m_bPhase1)&0x1F)<<2; // includes external length and repeat
|
||||
{
|
||||
u8 data = readmem(m_uRomAddrP2, m_bPhase1);
|
||||
|
||||
m_bStopP1 = bool(data & 0x80);
|
||||
m_bVoicedP1 = bool(data & 0x40);
|
||||
m_bSilenceP1 = bool(data & 0x20);
|
||||
m_uXRepeatP1 = data & 0x03;
|
||||
m_uLengthP1 = (data & 0x1f) << 2; // includes external length and repeat
|
||||
m_uDAR04To00P1 = 0;
|
||||
m_uCWARP1++; // gets ready for next DARMSB
|
||||
m_RomAddrP1 = (m_uDAR13To05P1<<3)|(m_uDAR04To00P1>>2); // remove lower two bits
|
||||
m_RomAddrP1 = (m_uDAR13To05P1 << 3) | (m_uDAR04To00P1 >> 2); // remove lower two bits
|
||||
|
||||
m_uOutputP1 = 7;
|
||||
if (m_bStart) m_uStateP1 = states::WORDWAIT;
|
||||
else m_uStateP1 = states::PLAY;
|
||||
m_uStateP1 = m_bStart ? states::WORDWAIT : states::PLAY;
|
||||
|
||||
if (m_uPrintLevel >= 2)
|
||||
printf("\n cw %d %d %d %d %d",m_bStopP1,m_bVoicedP1,m_bSilenceP1,m_uLengthP1>>4,m_uXRepeatP1);
|
||||
logerror("\n cw %d %d %d %d %d", m_bStopP1, m_bVoicedP1, m_bSilenceP1, m_uLengthP1 >> 4, m_uXRepeatP1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case states::PLAY:
|
||||
{
|
||||
@ -492,21 +494,22 @@ bool s14001a_device::Clock()
|
||||
{
|
||||
// pitch period end
|
||||
if (m_uPrintLevel >= 3)
|
||||
printf("\n ppe: RomAddr %03x",m_uRomAddrP2);
|
||||
logerror("\n ppe: RomAddr %03x", m_uRomAddrP2);
|
||||
|
||||
m_uNPitchPeriods++;
|
||||
if (m_bVoicedP2) m_uNVoiced++;
|
||||
if (m_bVoicedP2)
|
||||
m_uNVoiced++;
|
||||
}
|
||||
// end statistics
|
||||
|
||||
// modify output
|
||||
uint8_t uDeltaP2; // signal line
|
||||
uint8_t uIncrementP2; // signal lines
|
||||
u8 uDeltaP2; // signal line
|
||||
u8 uIncrementP2; // signal lines
|
||||
bool bAddP2; // signal line
|
||||
uDeltaP2 = Mux8To2(m_bVoicedP2,
|
||||
m_uLengthP2 & 0x03, // pitch period quater counter
|
||||
m_uDAR04To00P2 & 0x03, // two bit delta address within byte
|
||||
readmem(m_uRomAddrP2,m_bPhase1)
|
||||
readmem(m_uRomAddrP2, m_bPhase1)
|
||||
);
|
||||
CalculateIncrement(m_bVoicedP2,
|
||||
m_uLengthP2 & 0x03, // pitch period quater counter
|
||||
@ -542,42 +545,44 @@ bool s14001a_device::Clock()
|
||||
if (m_bVoicedP2 && m_bRepeatCarryP2) // repeat complete
|
||||
{
|
||||
m_uLengthP1 &= 0x70; // keep current "length"
|
||||
m_uLengthP1 |= (m_uXRepeatP1<<2); // load repeat from external repeat
|
||||
m_uLengthP1 |= (m_uXRepeatP1 << 2); // load repeat from external repeat
|
||||
m_uDAR13To05P1++; // advances ROM address 8 bytes
|
||||
if (m_uDAR13To05P1 >= 0x200) m_uDAR13To05P1 = 0; // emulate 9 bit counter
|
||||
if (m_uDAR13To05P1 >= 0x200)
|
||||
m_uDAR13To05P1 = 0; // emulate 9 bit counter
|
||||
}
|
||||
if (!m_bVoicedP2 && m_bDAR04To00CarryP2)
|
||||
{
|
||||
// unvoiced advances each quarter pitch period
|
||||
// note repeat counter not reloaded for non voiced speech
|
||||
m_uDAR13To05P1++; // advances ROM address 8 bytes
|
||||
if (m_uDAR13To05P1 >= 0x200) m_uDAR13To05P1 = 0; // emulate 9 bit counter
|
||||
if (m_uDAR13To05P1 >= 0x200)
|
||||
m_uDAR13To05P1 = 0; // emulate 9 bit counter
|
||||
}
|
||||
|
||||
// construct m_RomAddrP1
|
||||
m_RomAddrP1 = m_uDAR04To00P1;
|
||||
if (m_bVoicedP2 && m_uLengthP1&0x1) // mirroring
|
||||
{
|
||||
if (m_bVoicedP2 && m_uLengthP1 & 0x1) // mirroring
|
||||
m_RomAddrP1 ^= 0x1f; // count backwards
|
||||
}
|
||||
m_RomAddrP1 = (m_uDAR13To05P1<<3) | m_RomAddrP1>>2;
|
||||
m_RomAddrP1 = (m_uDAR13To05P1 << 3) | m_RomAddrP1 >> 2;
|
||||
|
||||
// next state
|
||||
if (m_bStart) m_uStateP1 = states::WORDWAIT;
|
||||
else if (m_bStopP2 && m_bLengthCarryP2) m_uStateP1 = states::DELAY;
|
||||
if (m_bStart)
|
||||
m_uStateP1 = states::WORDWAIT;
|
||||
else if (m_bStopP2 && m_bLengthCarryP2)
|
||||
m_uStateP1 = states::DELAY;
|
||||
else if (m_bLengthCarryP2)
|
||||
{
|
||||
m_uStateP1 = states::DARMSB;
|
||||
m_RomAddrP1 = m_uCWARP1; // output correct address
|
||||
}
|
||||
else m_uStateP1 = states::PLAY;
|
||||
else
|
||||
m_uStateP1 = states::PLAY;
|
||||
break;
|
||||
}
|
||||
|
||||
case states::DELAY:
|
||||
m_uOutputP1 = 7;
|
||||
if (m_bStart) m_uStateP1 = states::WORDWAIT;
|
||||
else m_uStateP1 = states::IDLE;
|
||||
m_uStateP1 = m_bStart ? states::WORDWAIT : states::IDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -592,7 +597,7 @@ void s14001a_device::ClearStatistics()
|
||||
m_uNControlWords = 0;
|
||||
}
|
||||
|
||||
void s14001a_device::GetStatistics(uint32_t &uNPitchPeriods, uint32_t &uNVoiced, uint32_t &uNControlWords)
|
||||
void s14001a_device::GetStatistics(u32 &uNPitchPeriods, u32 &uNVoiced, u32 &uNControlWords)
|
||||
{
|
||||
uNPitchPeriods = m_uNPitchPeriods;
|
||||
uNVoiced = m_uNVoiced;
|
||||
|
@ -8,10 +8,12 @@
|
||||
#ifndef MAME_SOUND_S14001A_H
|
||||
#define MAME_SOUND_S14001A_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class s14001a_device : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
s14001a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
s14001a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
// configuration helpers
|
||||
auto bsy() { return m_bsy_handler.bind(); }
|
||||
@ -20,9 +22,9 @@ public:
|
||||
int busy_r(); // /BUSY (pin 40)
|
||||
int romen_r(); // ROM /EN (pin 9)
|
||||
void start_w(int state); // START (pin 10)
|
||||
void data_w(uint8_t data); // 6-bit word
|
||||
void data_w(u8 data); // 6-bit word
|
||||
|
||||
void set_clock(uint32_t clock); // set new CLK frequency
|
||||
void set_clock(u32 clock); // set new CLK frequency
|
||||
void set_clock(const XTAL &xtal) { set_clock(xtal.value()); }
|
||||
void force_update(); // update stream, eg. before external ROM bankswitch
|
||||
|
||||
@ -34,13 +36,13 @@ protected:
|
||||
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
|
||||
|
||||
private:
|
||||
uint8_t readmem(uint16_t offset, bool phase);
|
||||
u8 readmem(u16 offset, bool phase);
|
||||
bool Clock(); // called once to toggle external clock twice
|
||||
|
||||
// emulator helper functions
|
||||
void ClearStatistics();
|
||||
void GetStatistics(uint32_t &uNPitchPeriods, uint32_t &uNVoiced, uint32_t &uNControlWords);
|
||||
void SetPrintLevel(uint32_t uPrintLevel) { m_uPrintLevel = uPrintLevel; }
|
||||
void GetStatistics(u32 &uNPitchPeriods, u32 &uNVoiced, u32 &uNControlWords);
|
||||
void SetPrintLevel(u32 uPrintLevel) { m_uPrintLevel = uPrintLevel; }
|
||||
|
||||
enum class states : u8
|
||||
{
|
||||
@ -54,7 +56,7 @@ private:
|
||||
DELAY
|
||||
};
|
||||
|
||||
required_region_ptr<uint8_t> m_SpeechRom;
|
||||
required_region_ptr<u8> m_SpeechRom;
|
||||
sound_stream * m_stream;
|
||||
|
||||
devcb_write_line m_bsy_handler;
|
||||
@ -67,15 +69,15 @@ private:
|
||||
states m_uStateP1; // 3 bits
|
||||
states m_uStateP2;
|
||||
|
||||
uint16_t m_uDAR13To05P1; // 9 MSBs of delta address register
|
||||
uint16_t m_uDAR13To05P2; // incrementing uDAR05To13 advances ROM address by 8 bytes
|
||||
u16 m_uDAR13To05P1; // 9 MSBs of delta address register
|
||||
u16 m_uDAR13To05P2; // incrementing uDAR05To13 advances ROM address by 8 bytes
|
||||
|
||||
uint16_t m_uDAR04To00P1; // 5 LSBs of delta address register
|
||||
uint16_t m_uDAR04To00P2; // 3 address ROM, 2 mux 8 bits of data into 2 bit delta
|
||||
u16 m_uDAR04To00P1; // 5 LSBs of delta address register
|
||||
u16 m_uDAR04To00P2; // 3 address ROM, 2 mux 8 bits of data into 2 bit delta
|
||||
// carry indicates end of quarter pitch period (32 cycles)
|
||||
|
||||
uint16_t m_uCWARP1; // 12 bits Control Word Address Register (syllable)
|
||||
uint16_t m_uCWARP2;
|
||||
u16 m_uCWARP1; // 12 bits Control Word Address Register (syllable)
|
||||
u16 m_uCWARP2;
|
||||
|
||||
bool m_bStopP1;
|
||||
bool m_bStopP2;
|
||||
@ -83,42 +85,42 @@ private:
|
||||
bool m_bVoicedP2;
|
||||
bool m_bSilenceP1;
|
||||
bool m_bSilenceP2;
|
||||
uint8_t m_uLengthP1; // 7 bits, upper three loaded from ROM length
|
||||
uint8_t m_uLengthP2; // middle two loaded from ROM repeat and/or uXRepeat
|
||||
u8 m_uLengthP1; // 7 bits, upper three loaded from ROM length
|
||||
u8 m_uLengthP2; // middle two loaded from ROM repeat and/or uXRepeat
|
||||
// bit 0 indicates mirror in voiced mode
|
||||
// bit 1 indicates internal silence in voiced mode
|
||||
// incremented each pitch period quarter
|
||||
|
||||
uint8_t m_uXRepeatP1; // 2 bits, loaded from ROM repeat
|
||||
uint8_t m_uXRepeatP2;
|
||||
uint8_t m_uDeltaOldP1; // 2 bit old delta
|
||||
uint8_t m_uDeltaOldP2;
|
||||
uint8_t m_uOutputP1; // 4 bits audio output, calculated during phase 1
|
||||
u8 m_uXRepeatP1; // 2 bits, loaded from ROM repeat
|
||||
u8 m_uXRepeatP2;
|
||||
u8 m_uDeltaOldP1; // 2 bit old delta
|
||||
u8 m_uDeltaOldP2;
|
||||
u8 m_uOutputP1; // 4 bits audio output, calculated during phase 1
|
||||
|
||||
// derived signals
|
||||
bool m_bDAR04To00CarryP2;
|
||||
bool m_bPPQCarryP2;
|
||||
bool m_bRepeatCarryP2;
|
||||
bool m_bLengthCarryP2;
|
||||
uint16_t m_RomAddrP1; // rom address
|
||||
u16 m_RomAddrP1; // rom address
|
||||
|
||||
// output pins
|
||||
uint8_t m_uOutputP2; // output changes on phase2
|
||||
uint16_t m_uRomAddrP2; // address pins change on phase 2
|
||||
u8 m_uOutputP2; // output changes on phase2
|
||||
u16 m_uRomAddrP2; // address pins change on phase 2
|
||||
bool m_bBusyP1; // busy changes on phase 1
|
||||
|
||||
// input pins
|
||||
bool m_bStart;
|
||||
uint8_t m_uWord; // 6 bit word number to be spoken
|
||||
u8 m_uWord; // 6 bit word number to be spoken
|
||||
|
||||
// emulator variables
|
||||
// statistics
|
||||
uint32_t m_uNPitchPeriods;
|
||||
uint32_t m_uNVoiced;
|
||||
uint32_t m_uNControlWords;
|
||||
u32 m_uNPitchPeriods;
|
||||
u32 m_uNVoiced;
|
||||
u32 m_uNControlWords;
|
||||
|
||||
// diagnostic output
|
||||
uint32_t m_uPrintLevel;
|
||||
u32 m_uPrintLevel;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(S14001A, s14001a_device)
|
||||
|
Loading…
Reference in New Issue
Block a user