Ejemplo n.º 1
0
static void s14001a_clock(S14001AChip *chip) /* called once per clock */
{
	UINT8 CurDelta; // Current delta

	/* on even clocks, audio output is floating, /romen is low so rom data bus is driven
         * on odd clocks, audio output is driven, /romen is high, state machine 2 is clocked
         */
	chip->oddeven = !(chip->oddeven); // invert the clock
	if (chip->oddeven == 0) // even clock
	{
#ifdef ACCURATE_SQUEAL
		chip->audioout = ALTFLAG; // flag to the renderer that this output should be the average of the last 8
#endif
		// DIGITAL INPUT *MIGHT* occur on the test pins occurs on this cycle?
	}
	else // odd clock
	{
		// fix dac output between samples. theoretically this might be unnecessary but it would require some messy logic in state 5 on the first sample load.
		// Note: this behavior is NOT accurate, and needs to be fixed. see TODO.
		if (chip->GlobalSilenceState || LOCALSILENCESTATE)
		{
			chip->DACOutput = SILENCE;
			chip->OldDelta = 2;
		}
		chip->audioout = (chip->GlobalSilenceState || LOCALSILENCESTATE) ? SILENCE : chip->DACOutput; // when either silence state is 1, output silence.
		// DIGITAL OUTPUT *might* be driven onto the test pins on this cycle?
		switch(chip->machineState) // HUUUUUGE switch statement
		{
		case 0: // idle state
			chip->nextstate = 0;
			break;
		case 1: // read starting syllable high byte from word table
			chip->SyllableAddress = 0; // clear syllable address
			chip->SyllableAddress |= chip->SpeechRom[(chip->LatchedWord<<1)]<<4;
			chip->nextstate = chip->resetState ? 1 : 2;
			break;
		case 2: // read starting syllable low byte from word table
			chip->SyllableAddress |= chip->SpeechRom[(chip->LatchedWord<<1)+1]>>4;
			chip->nextstate = 3;
			break;
		case 3: // read starting phone address
			chip->PhoneAddress = chip->SpeechRom[chip->SyllableAddress]<<4;
			chip->nextstate = 4;
			break;
		case 4: // read playback parameters and prepare for play
			chip->PlayParams = chip->SpeechRom[chip->SyllableAddress+1];
			chip->GlobalSilenceState = SILENCEFLAG; // load phone silence flag
			chip->LengthCounter = LENGTHCOUNT; // load length counter
			chip->RepeatCounter = REPEATCOUNT; // load repeat counter
			chip->OutputCounter = 0; // clear output counter and disable mirrored phoneme silence indirectly via LOCALSILENCESTATE
			chip->PhoneOffset = 0; // set offset within phone to zero
			chip->OldDelta = 0x2; // set old delta to 2 <- is this right?
			chip->DACOutput = SILENCE ; // set DAC output to center/silence position
			chip->nextstate = 5;
			break;
		case 5: // Play phone forward, shift = 0 (also load)
			CurDelta = (chip->SpeechRom[(chip->PhoneAddress)+chip->PhoneOffset]&0xc0)>>6; // grab current delta from high 2 bits of high nybble
			chip->DACOutput += DeltaTable[CurDelta][chip->OldDelta]; // send data to forward delta table and add result to accumulator
			chip->OldDelta = CurDelta; // Move current delta to old
			chip->nextstate = 6;
			break;
		case 6: // Play phone forward, shift = 2
			CurDelta = (chip->SpeechRom[(chip->PhoneAddress)+chip->PhoneOffset]&0x30)>>4; // grab current delta from low 2 bits of high nybble
			chip->DACOutput += DeltaTable[CurDelta][chip->OldDelta]; // send data to forward delta table and add result to accumulator
			chip->OldDelta = CurDelta; // Move current delta to old
			chip->nextstate = 7;
			break;
		case 7: // Play phone forward, shift = 4
			CurDelta = (chip->SpeechRom[(chip->PhoneAddress)+chip->PhoneOffset]&0xc)>>2; // grab current delta from high 2 bits of low nybble
			chip->DACOutput += DeltaTable[CurDelta][chip->OldDelta]; // send data to forward delta table and add result to accumulator
			chip->OldDelta = CurDelta; // Move current delta to old
			chip->nextstate = 8;
			break;
		case 8: // Play phone forward, shift = 6 (increment address if needed)
			CurDelta = chip->SpeechRom[(chip->PhoneAddress)+chip->PhoneOffset]&0x3; // grab current delta from low 2 bits of low nybble
			chip->DACOutput += DeltaTable[CurDelta][chip->OldDelta]; // send data to forward delta table and add result to accumulator
			chip->OldDelta = CurDelta; // Move current delta to old
			chip->PhoneOffset++; // increment phone offset
			if (chip->PhoneOffset == 0x8) // if we're now done this phone
			{
				/* call the PostPhoneme Function */
				PostPhoneme(chip);
			}
			else
			{
				chip->nextstate = 5;
			}
			break;
		case 9: // Play phone backward, shift = 6 (also load)
			CurDelta = (chip->SpeechRom[(chip->PhoneAddress)+chip->PhoneOffset]&0x3); // grab current delta from low 2 bits of low nybble
			if (chip->laststate != 8) // ignore first (bogus) dac change in mirrored backwards mode. observations and the patent show this.
			{
				chip->DACOutput -= DeltaTable[chip->OldDelta][CurDelta]; // send data to forward delta table and subtract result from accumulator
			}
			chip->OldDelta = CurDelta; // Move current delta to old
			chip->nextstate = 10;
			break;
		case 10: // Play phone backward, shift = 4
			CurDelta = (chip->SpeechRom[(chip->PhoneAddress)+chip->PhoneOffset]&0xc)>>2; // grab current delta from high 2 bits of low nybble
			chip->DACOutput -= DeltaTable[chip->OldDelta][CurDelta]; // send data to forward delta table and subtract result from accumulator
			chip->OldDelta = CurDelta; // Move current delta to old
			chip->nextstate = 11;
			break;
		case 11: // Play phone backward, shift = 2
			CurDelta = (chip->SpeechRom[(chip->PhoneAddress)+chip->PhoneOffset]&0x30)>>4; // grab current delta from low 2 bits of high nybble
			chip->DACOutput -= DeltaTable[chip->OldDelta][CurDelta]; // send data to forward delta table and subtract result from accumulator
			chip->OldDelta = CurDelta; // Move current delta to old
			chip->nextstate = 12;
			break;
		case 12: // Play phone backward, shift = 0 (increment address if needed)
			CurDelta = (chip->SpeechRom[(chip->PhoneAddress)+chip->PhoneOffset]&0xc0)>>6; // grab current delta from high 2 bits of high nybble
			chip->DACOutput -= DeltaTable[chip->OldDelta][CurDelta]; // send data to forward delta table and subtract result from accumulator
			chip->OldDelta = CurDelta; // Move current delta to old
			chip->PhoneOffset--; // decrement phone offset
			if (chip->PhoneOffset == 0xFF) // if we're now done this phone
			{
				/* call the PostPhoneme() function */
				PostPhoneme(chip);
			}
			else
			{
				chip->nextstate = 9;
			}
			break;
		case 13: // For those pedantic among us, consume an extra two clocks like the real chip does.
			chip->nextstate = 0;
			break;
		}
#ifdef DEBUGSTATE
		fprintf(stderr, "Machine state is now %d, was %d, PhoneOffset is %d\n", chip->nextstate, chip->machineState, chip->PhoneOffset);
#endif
		chip->laststate = chip->machineState;
		chip->machineState = chip->nextstate;

	        /* the dac is 4 bits wide. if a delta step forced it outside of 4 bits, mask it back over here */
	        chip->DACOutput &= 0xF;
	}
}
Ejemplo n.º 2
0
void s14001a_clock(void) /* called once per clock */
{
	UINT8 CurDelta; // Current delta

	/* on even clocks, audio output is floating, /romen is low so rom data bus is driven, input is latched?
	 * on odd clocks, audio output is driven, /romen is high, state machine 2 is clocked */
	oddeven = !(oddeven); // invert the clock
	if (oddeven == 0) // even clock
        {
		audioout = audiofilter(); // function to handle output filtering by internal capacitance based on clock speed and such
#ifdef PINMAME
		if (!machineState) audioout = SILENCE;
#endif
		shiftIntoFilter(audioout); // shift over all the filter outputs and stick in audioout
	}
	else // odd clock
	{
		// fix dac output between samples. theoretically this might be unnecessary but it would require some messy logic in state 5 on the first sample load.
		if (GlobalSilenceState || LOCALSILENCESTATE)
		{
			DACOutput = SILENCE;
			OldDelta = 2;
		}
		audioout = (GlobalSilenceState || LOCALSILENCESTATE) ? SILENCE : DACOutput; // when either silence state is 1, output silence.
#ifdef PINMAME
		if (!machineState) audioout = SILENCE;
#endif
		shiftIntoFilter(audioout); // shift over all the filter outputs and stick in audioout
		switch(machineState)
		{
		case 0: // idle state
			nextstate = 0;
			break;
		case 1: // read starting syllable high byte from word table
			SyllableAddress = 0; // clear syllable address
			SyllableAddress |= s14001a_readmem(LatchedWord<<1)<<4;
			nextstate = resetState ? 1 : 2;
			break;
		case 2: // read starting syllable low byte from word table
			SyllableAddress |= s14001a_readmem((LatchedWord<<1)+1)>>4;
			nextstate = 3;
			break;
		case 3: // read starting phone address
			PhoneAddress = s14001a_readmem(SyllableAddress)<<4;
			nextstate = 4;
			break;
		case 4: // read playback parameters and prepare for play
			PlayParams = s14001a_readmem(SyllableAddress+1);
			GlobalSilenceState = SILENCEFLAG; // load phone silence flag
			LengthCounter = LENGTHCOUNT; // load length counter
			RepeatCounter = REPEATCOUNT; // load repeat counter
			OutputCounter = 0; // clear output counter and disable mirrored phoneme silence indirectly via LOCALSILENCESTATE
			PhoneOffset = 0; // set offset within phone to zero
			OldDelta = 0x2; // set old delta to 2 <- is this right?
			DACOutput = 0x88; // set DAC output to center/silence position (0x88)
			nextstate = 5;
			break;
		case 5: // Play phone forward, shift = 0 (also load)
			CurDelta = (s14001a_readmem((PhoneAddress)+PhoneOffset)&0xc0)>>6; // grab current delta from high 2 bits of high nybble
			DACOutput += DeltaTable[CurDelta][OldDelta]; // send data to forward delta table and add result to accumulator
			OldDelta = CurDelta; // Move current delta to old
			nextstate = 6;
			break;
		case 6: // Play phone forward, shift = 2
	   		CurDelta = (s14001a_readmem((PhoneAddress)+PhoneOffset)&0x30)>>4; // grab current delta from low 2 bits of high nybble
			DACOutput += DeltaTable[CurDelta][OldDelta]; // send data to forward delta table and add result to accumulator
			OldDelta = CurDelta; // Move current delta to old
			nextstate = 7;
			break;
		case 7: // Play phone forward, shift = 4
			CurDelta = (s14001a_readmem((PhoneAddress)+PhoneOffset)&0xc)>>2; // grab current delta from high 2 bits of low nybble
			DACOutput += DeltaTable[CurDelta][OldDelta]; // send data to forward delta table and add result to accumulator
			OldDelta = CurDelta; // Move current delta to old
			nextstate = 8;
			break;
		case 8: // Play phone forward, shift = 6 (increment address if needed)
			CurDelta = s14001a_readmem((PhoneAddress)+PhoneOffset)&0x3; // grab current delta from low 2 bits of low nybble
			DACOutput += DeltaTable[CurDelta][OldDelta]; // send data to forward delta table and add result to accumulator
			OldDelta = CurDelta; // Move current delta to old
			PhoneOffset++; // increment phone offset
			if (PhoneOffset == 0x8) // if we're now done this phone
			{
				/* call the PostPhoneme Function */
				PostPhoneme();
			}
			else
			{
				nextstate = 5;
			}
			break;
		case 9: // Play phone backward, shift = 6 (also load)
			CurDelta = (s14001a_readmem((PhoneAddress)+PhoneOffset)&0x3); // grab current delta from low 2 bits of low nybble
			if (laststate != 8) // ignore first (bogus) dac change in mirrored backwards mode. observations and the patent show this.
			{
				DACOutput -= DeltaTable[OldDelta][CurDelta]; // send data to forward delta table and subtract result from accumulator
			}
			OldDelta = CurDelta; // Move current delta to old
			nextstate = 10;
			break;
		case 10: // Play phone backward, shift = 4
			CurDelta = (s14001a_readmem((PhoneAddress)+PhoneOffset)&0xc)>>2; // grab current delta from high 2 bits of low nybble
			DACOutput -= DeltaTable[OldDelta][CurDelta]; // send data to forward delta table and subtract result from accumulator
			OldDelta = CurDelta; // Move current delta to old
			nextstate = 11;
			break;
		case 11: // Play phone backward, shift = 2
			CurDelta = (s14001a_readmem((PhoneAddress)+PhoneOffset)&0x30)>>4; // grab current delta from low 2 bits of high nybble
			DACOutput -= DeltaTable[OldDelta][CurDelta]; // send data to forward delta table and subtract result from accumulator
			OldDelta = CurDelta; // Move current delta to old
			nextstate = 12;
			break;
		case 12: // Play phone backward, shift = 0 (increment address if needed)
			CurDelta = (s14001a_readmem((PhoneAddress)+PhoneOffset)&0xc0)>>6; // grab current delta from high 2 bits of high nybble
			DACOutput -= DeltaTable[OldDelta][CurDelta]; // send data to forward delta table and subtract result from accumulator
			OldDelta = CurDelta; // Move current delta to old
			PhoneOffset--; // decrement phone offset
			if (PhoneOffset == 0xFF) // if we're now done this phone
			{
				/* call the PostPhoneme() function */
				PostPhoneme();
			}
			else
			{
				nextstate = 9;
			}
			break;
		case 13: // For those pedantic among us, consume an extra two clocks like the real chip does.
			nextstate = 0;
			break;
		}
#ifdef DEBUGSTATE
		fprintf(stderr, "Machine state is now %d, was %d, PhoneOffset is %d\n", nextstate, machineState, PhoneOffset);
#endif
		laststate = machineState;
		machineState = nextstate;
	}
}