s14001a: shorthand variable types, small cleanup

This commit is contained in:
hap 2024-08-11 15:05:03 +02:00
parent a8d909a02a
commit d352702d22
2 changed files with 134 additions and 127 deletions

View File

@ -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,38 +494,39 @@ 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
bool bAddP2; // signal line
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)
m_uLengthP2 & 0x03, // pitch period quater counter
m_uDAR04To00P2 & 0x03, // two bit delta address within byte
readmem(m_uRomAddrP2, m_bPhase1)
);
CalculateIncrement(m_bVoicedP2,
m_uLengthP2 & 0x03, // pitch period quater counter
m_uDAR04To00P2 == 0, // pitch period quarter start
uDeltaP2,
m_uDeltaOldP2, // input
m_uDeltaOldP1, // output
uIncrementP2, // output 0, 1, or 3
bAddP2 // output
m_uLengthP2 & 0x03, // pitch period quater counter
m_uDAR04To00P2 == 0, // pitch period quarter start
uDeltaP2,
m_uDeltaOldP2, // input
m_uDeltaOldP1, // output
uIncrementP2, // output 0, 1, or 3
bAddP2 // output
);
m_uOutputP1 = CalculateOutput(m_bVoicedP2,
m_bSilenceP2,
m_uLengthP2 & 0x03, // pitch period quater counter
m_uDAR04To00P2 == 0, // pitch period quarter start
m_uOutputP2, // last output
uIncrementP2,
bAddP2
m_bSilenceP2,
m_uLengthP2 & 0x03, // pitch period quater counter
m_uDAR04To00P2 == 0, // pitch period quarter start
m_uOutputP2, // last output
uIncrementP2,
bAddP2
);
// advance counters
@ -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;

View File

@ -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,11 +22,11 @@ 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
void force_update(); // update stream, eg. before external ROM bankswitch
protected:
// device-level overrides
@ -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,28 +56,28 @@ 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;
devcb_read8 m_ext_read_handler;
// internal state
bool m_bPhase1; // 1 bit internal clock
bool m_bPhase1; // 1 bit internal clock
// registers
states m_uStateP1; // 3 bits
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
// carry indicates end of quarter pitch period (32 cycles)
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
// bit 0 indicates mirror in voiced mode
// bit 1 indicates internal silence in voiced mode
// incremented each pitch period quarter
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
bool m_bBusyP1; // busy changes on phase 1
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)