Previous 15994 Revisions Next

r15500 Monday 25th June, 2012 at 11:33:37 UTC by Michael Zapf
Re-implementation as class, appended to legacy version [Michael Zapf]
(nw)
[src/emu/sound]tms5220.c tms5220.h

src/emu/sound/tms5220.c
r15499r15500
332332// above debugs the tms5220_data_r and data_w access methods which actually respect rs and ws
333333
334334#define MAX_SAMPLE_CHUNK   512
335#define FIFO_SIZE 16
336335
337336/* Variants */
338337
r15499r15500
20392038DEFINE_LEGACY_SOUND_DEVICE(TMS5220, tms5220);
20402039DEFINE_LEGACY_SOUND_DEVICE(TMC0285, tmc0285);
20412040DEFINE_LEGACY_SOUND_DEVICE(TMS5200, tms5200);
2041
2042
2043/******************************************************************************
2044   New class implementation
2045******************************************************************************/
2046
2047#define M_INTERP_SHIFT >> m_coeff->interp_coeff[m_interp_period]
2048
2049tms52xx_device::tms52xx_device(const machine_config &mconfig, device_type type,  const char *name, const char *tag, const struct tms5100_coeffs* coeffs, const int var, device_t *owner, UINT32 clock)
2050   : device_t(mconfig, type, name, tag, owner, clock),
2051     device_sound_interface(mconfig, *this),
2052     m_variant(var),
2053     m_coeff(coeffs)
2054{
2055}
2056
2057
2058tms5220n_device::tms5220n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
2059   : tms52xx_device(mconfig, TMS5220N, "TMS5220N", tag, &tms5220_coeff, TMS5220_IS_5220, owner, clock)
2060{
2061}
2062
2063tms5220cn_device::tms5220cn_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
2064   : tms52xx_device(mconfig, TMS5220CN, "TMS5220CN", tag, &tms5220c_coeff, TMS5220_IS_5220C, owner, clock)
2065{
2066}
2067
2068tmc0285n_device::tmc0285n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
2069   : tms52xx_device(mconfig, TMC0285N, "TMC0285N", tag, &tms5200_coeff, TMS5220_IS_TMC0285, owner, clock)
2070{
2071}
2072
2073tms5200n_device::tms5200n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
2074   : tms52xx_device(mconfig, TMS5200N, "TMS5200N", tag, &tms5200_coeff, TMS5220_IS_5200, owner, clock)
2075{
2076}
2077
2078void tms52xx_device::device_start()
2079{
2080   const tms52xx_config *conf = reinterpret_cast<const tms52xx_config *>(static_config());
2081   //m_table = region();
2082
2083   /* resolve irq and readyq line */
2084   m_irq_func.resolve(conf->irq_func, *this);
2085   m_readyq_func.resolve(conf->readyq_func, *this);
2086   m_read_mem.resolve(conf->read_mem, *this);
2087   m_load_address.resolve(conf->load_address, *this);
2088   m_read_and_branch.resolve(conf->read_and_branch, *this);
2089
2090   /* initialize a stream */
2091   m_stream = machine().sound().stream_alloc(*this, 0, 1, clock() / 80, this);
2092
2093   /*if (m_table == NULL)
2094    {
2095        assert_always(m_conf->M0_callback != NULL, "Missing _mandatory_ 'M0_callback' function pointer in the TMS5110 interface\n  This function is used by TMS5220 to call for a new single bit\n  needed to generate the speech when in VSM mode\n  Aborting startup...\n");
2096        m_M0_callback = conf->M0_callback;
2097        m_set_load_address = conf->load_address;
2098    }
2099    else
2100    {
2101        m_M0_callback = speech_rom_read_bit;
2102        m_set_load_address = speech_rom_set_addr;
2103    }*/
2104
2105   /* not during reset which is called frm within a write! */
2106   m_io_ready = true;
2107   m_true_timing = false;
2108   m_rs_ws = 0x03; // rs and ws are assumed to be inactive on device startup
2109
2110   m_ready_timer = timer_alloc(0);
2111
2112   register_for_save_states();
2113}
2114
2115void tms52xx_device::device_reset()
2116{
2117   m_digital_select = FORCE_DIGITAL;         // assume analog output
2118   // initialize the FIFO */
2119   // memset(tms->fifo, 0, sizeof(tms->fifo));
2120   m_fifo_head = 0;
2121   m_fifo_tail = 0;
2122   m_fifo_count = 0;
2123   m_fifo_bits_taken = 0;
2124
2125   // initialize the chip state
2126   // Note that we do not actually clear IRQ on start-up: IRQ is even raised
2127   // if m_buffer_empty or m_buffer_low are 0
2128   m_speaking_now = false;
2129   m_speak_external = false;
2130   m_talk_status = false;
2131   m_irq_pin = 0;      // CLEAR_LINE
2132   m_ready_pin = 0;   // CLEAR_LINE
2133
2134   set_interrupt_state(0);         // CLEAR_LINE
2135   update_ready_state();
2136   m_buffer_empty = true;
2137   m_buffer_low = true;
2138
2139   m_RDB_flag = false;
2140
2141   /* initialize the energy/pitch/k states */
2142#ifdef PERFECT_INTERPOLATION_HACK
2143   m_old_frame_energy_idx = 0;
2144   m_old_frame_pitch_idx = 0;
2145   memset(m_old_frame_k_idx, 0, sizeof(m_old_frame_k_idx));
2146#endif
2147
2148   m_new_frame_energy_idx = 0;
2149   m_current_energy = 0;
2150   m_target_energy = 0;
2151   m_new_frame_pitch_idx = 0;
2152   m_current_pitch = 0;
2153   m_target_pitch = 0;
2154
2155   memset(m_new_frame_k_idx, 0, sizeof(m_new_frame_k_idx));
2156   memset(m_current_k, 0, sizeof(m_current_k));
2157   memset(m_target_k, 0, sizeof(m_target_k));
2158
2159   /* initialize the sample generators */
2160   m_inhibit = true;
2161   m_subcycle = 0;
2162   m_tms5220c_rate = 0;
2163   m_pitch_count = 0;
2164   m_PC = 0;
2165
2166   m_subc_reload = FORCE_SUBC_RELOAD;
2167   m_OLDE = 1;
2168   m_OLDP = 1;
2169
2170   m_interp_period = reload_table[m_tms5220c_rate&0x3];
2171   m_RNG = 0x1FFF;
2172   memset(m_u, 0, sizeof(m_u));
2173   memset(m_x, 0, sizeof(m_x));
2174
2175   m_load_address(0, 0);
2176   m_schedule_dummy_read = true;
2177}
2178
2179/******************************************************************************
2180     set_interrupt_state -- generate an interrupt
2181*******************************************************************************/
2182
2183void tms52xx_device::set_interrupt_state(int state)
2184{
2185#ifdef DEBUG_PIN_READS
2186   logerror("tms52xx: irq pin set to state %d\n", state);
2187#endif
2188    if (state != m_irq_pin) m_irq_func(!state);
2189    m_irq_pin = state;
2190}
2191
2192/******************************************************************************
2193     update_ready_state -- update the ready line
2194*******************************************************************************/
2195
2196void tms52xx_device::update_ready_state()
2197{
2198   int state = ready_read();
2199#ifdef DEBUG_PIN_READS
2200   logerror("tms52xx: ready pin set to state %d\n", state);
2201#endif
2202   if (state != m_ready_pin) m_readyq_func(!state);
2203   m_ready_pin = state;
2204}
2205
2206/******************************************************************************
2207     tms5220_set_frequency -- adjusts the playback frequency
2208*******************************************************************************/
2209
2210void tms52xx_device::set_frequency(int frequency)
2211{
2212   m_stream->set_sample_rate(frequency / 80);
2213   m_clock = frequency;
2214}
2215
2216/******************************************************************************
2217     tms5220_update -- update the sound chip so that it is in sync with CPU execution
2218*******************************************************************************/
2219
2220void tms52xx_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
2221{
2222   INT16 sample_data[MAX_SAMPLE_CHUNK];
2223   stream_sample_t *buffer = outputs[0];
2224
2225   /* loop while we still have samples to generate */
2226   while (samples>0)
2227   {
2228      int length = (samples > MAX_SAMPLE_CHUNK) ? MAX_SAMPLE_CHUNK : samples;
2229      int index;
2230
2231      /* generate the samples and copy to the target buffer */
2232      process(sample_data, length);
2233      for (index = 0; index < length; index++)
2234         *buffer++ = sample_data[index];
2235
2236      /* account for the samples */
2237      samples -= length;
2238   }
2239}
2240
2241/******************************************************************************
2242    process -- fill the buffer with a specific number of samples
2243*******************************************************************************/
2244
2245void tms52xx_device::process(INT16 *buffer, unsigned int size)
2246{
2247   int buf_count=0;
2248   int i, bitout;
2249   bool zpar;
2250   INT32 this_sample;
2251
2252   // The following gotos are probably safe to remove
2253   // if we're empty and still not speaking, fill with nothingness
2254   if (!m_speaking_now) goto empty;
2255
2256   // if speak external is set, but talk status is not (yet) set,
2257   // wait for buffer low to clear
2258   if (!m_talk_status && m_speak_external && m_buffer_low) goto empty;
2259
2260   // loop until the buffer is full or we've stopped speaking
2261   while ((size > 0) && m_speaking_now)
2262   {
2263      // if it is the appropriate time to update the old energy/pitch idxes,
2264      // i.e. when IP=7, PC=12, T=17, subcycle=2, do so. Since IP=7 PC=12 T=17
2265      // is JUST BEFORE the transition to IP=0 PC=0 T=0 sybcycle=(0 or 1),
2266      // which happens 4 T-cycles later), we change on the latter.
2267      if ((m_interp_period == 0) && (m_PC == 0) && (m_subcycle < 2))
2268      {
2269         m_OLDE = (m_new_frame_energy_idx == 0);
2270         m_OLDP = (m_new_frame_pitch_idx == 0);
2271      }
2272
2273      //if we're ready for a new frame to be applied, i.e. when IP=0, PC=12, Sub=1
2274      // (In reality, the frame was really loaded incrementally during the
2275      // entire IP=0 PC=x time period, but it doesn't affect anything until IP=0 PC=12 happens)
2276      if ((m_interp_period == 0) && (m_PC == 12) && (m_subcycle == 1))
2277      {
2278         // HACK for regression testing, be sure to comment out before release!
2279         // m_RNG = 0x1234;
2280         // end HACK
2281
2282         // appropriately override the interp count if needed; this will be incremented after the frame parse!
2283         m_interp_period = reload_table[m_tms5220c_rate & 0x3];
2284
2285#ifdef PERFECT_INTERPOLATION_HACK
2286         // remember previous frame energy, pitch, and coefficients
2287         m_old_frame_energy_idx = m_new_frame_energy_idx;
2288         m_old_frame_pitch_idx = m_new_frame_pitch_idx;
2289         for (i = 0; i < m_coeff->num_k; i++)
2290            m_old_frame_k_idx[i] = m_new_frame_k_idx[i];
2291#endif
2292
2293         // if the talk status was clear last frame, halt speech now.
2294         if (m_talk_status == false)
2295         {
2296#ifdef DEBUG_GENERATION
2297            fprintf(stderr,"tms5220_process: processing frame: talk status = 0 caused by stop frame or buffer empty, halting speech.\n");
2298#endif
2299            m_speaking_now = false; // finally halt speech
2300            goto empty;
2301         }
2302
2303         // Parse a new frame into the new_target_energy, new_target_pitch and new_target_k[]
2304         parse_frame();
2305#ifdef DEBUG_PARSE_FRAME_DUMP
2306         fprintf(stderr,"\n");
2307#endif
2308         // if the new frame is a stop frame, set an interrupt and set talk status to 0
2309         if (M_NEW_FRAME_STOP_FLAG == 1)
2310         {
2311            m_talk_status = false;
2312            m_speak_external = false;
2313            set_interrupt_state(1);
2314            update_status_and_ints();
2315         }
2316
2317         // in all cases where interpolation would be inhibited, set the inhibit flag; otherwise clear it.
2318         // Interpolation inhibit cases:
2319         // * Old frame was voiced, new is unvoiced
2320         // * Old frame was silence/zero energy, new has nonzero energy
2321         // * Old frame was unvoiced, new is voiced
2322
2323         if ( ((M_OLD_FRAME_UNVOICED_FLAG == false) && (M_NEW_FRAME_UNVOICED_FLAG == true))
2324            || ((M_OLD_FRAME_UNVOICED_FLAG == true) && (M_NEW_FRAME_UNVOICED_FLAG == false))
2325            || ((M_OLD_FRAME_SILENCE_FLAG == true) && (M_NEW_FRAME_SILENCE_FLAG == false)) )
2326            m_inhibit = true;
2327         else // normal frame, normal interpolation
2328            m_inhibit = false;
2329
2330         // load new frame targets from tables, using parsed indices
2331         m_target_energy = m_coeff->energytable[m_new_frame_energy_idx];
2332         m_target_pitch = m_coeff->pitchtable[m_new_frame_pitch_idx];
2333         zpar = M_NEW_FRAME_UNVOICED_FLAG; // find out if parameters k5-k10 should be zeroed
2334         for (i = 0; i < 4; i++)
2335            m_target_k[i] = m_coeff->ktable[i][m_new_frame_k_idx[i]];
2336         for (i = 4; i < m_coeff->num_k; i++)
2337            m_target_k[i] = (m_coeff->ktable[i][m_new_frame_k_idx[i]] * (1-zpar));
2338
2339#ifdef DEBUG_GENERATION
2340         /* Debug info for current parsed frame */
2341         fprintf(stderr, "OLDE: %d; OLDP: %d; ", m_OLDE, m_OLDP);
2342         fprintf(stderr,"Processing frame: ");
2343         if (m_inhibit == 0)
2344            fprintf(stderr, "Normal Frame\n");
2345         else
2346            fprintf(stderr,"Interpolation Inhibited\n");
2347         fprintf(stderr,"*** current Energy, Pitch and Ks =      %04d,   %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",
2348            m_current_energy, m_current_pitch,
2349            m_current_k[0], m_current_k[1],   m_current_k[2], m_current_k[3],
2350            m_current_k[4], m_current_k[5], m_current_k[6], m_current_k[7],
2351            m_current_k[8], m_current_k[9]);
2352         fprintf(stderr,"*** target Energy(idx), Pitch, and Ks = %04d(%x),%04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",
2353            m_target_energy, m_new_frame_energy_idx, m_target_pitch,
2354            m_target_k[0], m_target_k[1], m_target_k[2], m_target_k[3],
2355            m_target_k[4], m_target_k[5], m_target_k[6], m_target_k[7],
2356            m_target_k[8], m_target_k[9]);
2357#endif
2358
2359         /* if TS is now 0, ramp the energy down to 0. Is this really correct to hardware? */
2360         if (!m_talk_status)
2361         {
2362#ifdef DEBUG_GENERATION
2363            fprintf(stderr,"Talk status is 0, forcing target energy to 0\n");
2364#endif
2365            m_target_energy = 0;
2366         }
2367      }
2368      else // Not a new frame, just interpolate the existing frame.
2369      {
2370         bool inhibit_state = (m_inhibit && (m_interp_period != 0)); // disable inhibit when reaching the last interp period, but don't overwrite the tms->inhibit value
2371#ifdef PERFECT_INTERPOLATION_HACK
2372         int samples_per_frame = (m_subc_reload!=0)? 175:266;      // either (13 A cycles + 12 B cycles) * 7 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 7 interps for SPKSLOW
2373         //int samples_per_frame = (m_subc_reload!=0)?200:304; // either (13 A cycles + 12 B cycles) * 8 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 8 interps for SPKSLOW
2374         int current_sample = (tms->subcycle - tms->subc_reload)+(tms->PC*(3-tms->subc_reload))+((tms->subc_reload?25:38)*((tms->interp_period-1)&7));
2375
2376         zpar = M_OLD_FRAME_UNVOICED_FLAG;
2377         //fprintf(stderr, "CS: %03d", current_sample);
2378         // reset the current energy, pitch, etc to what it was at frame start
2379         m_current_energy = m_coeff->energytable[m_old_frame_energy_idx];
2380         m_current_pitch = m_coeff->pitchtable[m_old_frame_pitch_idx];
2381         for (i = 0; i < 4; i++)
2382            m_current_k[i] = m_coeff->ktable[i][m_old_frame_k_idx[i]];
2383         for (i = 4; i < m_coeff->num_k; i++)
2384            m_current_k[i] = (m_coeff->ktable[i][m_old_frame_k_idx[i]] * (1-zpar));
2385         // now adjust each value to be exactly correct for each of the samples per frame
2386         if (m_interp_period != 0) // if we're still interpolating...
2387         {
2388            if (!inhibit_state)
2389            {
2390               m_current_energy += ((m_target_energy - m_current_energy)*current_sample)/samples_per_frame;
2391               m_current_pitch += ((m_target_pitch - m_current_pitch)*current_sample)/samples_per_frame;
2392               for (i = 0; i < m_coeff->num_k; i++)
2393               {
2394                  m_current_k[i] += ((m_target_k[i] - m_current_k[i])*current_sample)/samples_per_frame;
2395               }
2396            }
2397         }
2398         else // we're done, play this frame for 1/8 frame.
2399         {
2400            m_current_energy = m_target_energy;
2401            m_current_pitch = m_target_pitch;
2402            for (i = 0; i < m_coeff->num_k; i++)
2403               m_current_k[i] = m_target_k[i];
2404         }
2405#else
2406         // Updates to parameters only happen on subcycle '2' (B cycle) of PCs.
2407         if (m_subcycle == 2)
2408         {
2409            if (!inhibit_state)
2410            {
2411               switch(m_PC)
2412               {
2413               case 0: // PC = 0, B cycle, write updated energy
2414                  m_current_energy += ((m_target_energy - m_current_energy) M_INTERP_SHIFT);
2415                  break;
2416               case 1: /* PC = 1, B cycle, write updated pitch */
2417                  m_current_pitch += ((m_target_pitch - m_current_pitch) M_INTERP_SHIFT);
2418                  break;
2419               case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11:
2420                  /* PC = 2 through 11, B cycle, write updated K1 through K10 */
2421                  m_current_k[m_PC-2] += ((m_target_k[m_PC-2] - m_current_k[m_PC-2]) M_INTERP_SHIFT);
2422                  break;
2423               case 12: /* PC = 12, do nothing */
2424                  break;
2425               }
2426            }
2427         }
2428#endif
2429      }
2430
2431      // calculate the output
2432      if (M_OLD_FRAME_UNVOICED_FLAG == true)
2433      {
2434         // generate unvoiced samples here
2435#ifndef UNVOICED_HACK
2436         if (m_RNG & 1)
2437            m_excitation_data = ~0x3F; // according to the patent it is (either + or -) half of the maximum value in the chirp table, so either 01000000(0x40) or 11000000(0xC0)
2438         else
2439            m_excitation_data = 0x40;
2440#else // hack to double unvoiced strength, doesn't match patent
2441         if (m_RNG & 1)
2442            m_excitation_data = ~0x7F;
2443         else
2444            m_excitation_data = 0x80;
2445#endif
2446      }
2447      else // (M_OLD_FRAME_UNVOICED_FLAG == false)
2448      {
2449         // generate voiced samples here
2450         // US patent 4331836 Figure 14B shows, and logic would hold, that a pitch based chirp
2451         // function has a chirp/peak and then a long chain of zeroes.
2452         // The last entry of the chirp rom is at address 0b110011 (51d), the 52nd sample,
2453         // and if the address reaches that point the ADDRESS incrementer is
2454         // disabled, forcing all samples beyond 51d to be == 51d
2455         // (address 51d holds zeroes, which may or may not be inverted to -1)
2456
2457         if (m_pitch_count >= 51)
2458            m_excitation_data = m_coeff->chirptable[51];
2459         else // tms->pitch_count < 51
2460            m_excitation_data = m_coeff->chirptable[m_pitch_count];
2461#ifdef VOICED_INV_HACK
2462         // invert waveform
2463         if (m_pitch_count >= 51)
2464            m_excitation_data = ~m_coeff->chirptable[51];
2465         else // tms->pitch_count < 51
2466            m_excitation_data = ~m_coeff->chirptable[m_pitch_count];
2467#endif
2468#ifdef VOICED_ZERO_HACK
2469         // 0 and >=51 are -128, as implied by qboxpro tables
2470         if ((m_pitch_count == 0) | (m_pitch_count >= 51))
2471            m_excitation_data = -128;
2472         else /*tms->pitch_count < 51 && > 0*/
2473            m_excitation_data = m_coeff->chirptable[m_pitch_count];
2474#endif
2475#ifdef VOICED_PULSE_HACK
2476         // if pitch is between 1 and PWIDTH+1, out = PAMP, if between PWIDTH+1 and (2*PWIDTH)+1, out ~PAMP, else out = 0
2477         if (m_pitch_count == 0)
2478            m_excitation_data = 0;
2479         else if (m_pitch_count < PWIDTH+1)
2480            m_excitation_data = PAMP;
2481         else if (m_pitch_count < (PWIDTH*2)+1)
2482            m_excitation_data = ~PAMP;
2483         else
2484            m_excitation_data = 0;
2485#endif
2486#ifdef VOICED_PULSE_MONOPOLAR_HACK
2487         // if pitch is between 1 and PWIDTH+1, out = PAMP, else out = 0
2488         if (m_pitch_count == 0)
2489            m_excitation_data = 0;
2490         else if (m_pitch_count < PWIDTH+1)
2491            m_excitation_data = PAMP;
2492         else
2493            m_excitation_data = 0;
2494#endif
2495      }
2496
2497      // Update LFSR *20* times every sample (once per T cycle), like patent shows
2498      for (i=0; i<20; i++)
2499      {
2500         bitout = ((m_RNG >> 12) & 1) ^
2501               ((m_RNG >>  3) & 1) ^
2502               ((m_RNG >>  2) & 1) ^
2503               ((m_RNG >>  0) & 1);
2504         m_RNG <<= 1;
2505         m_RNG |= bitout;
2506      }
2507
2508      this_sample = lattice_filter(); // execute lattice filter
2509#ifdef DEBUG_GENERATION_VERBOSE
2510      //fprintf(stderr,"C:%01d; ",tms->subcycle);
2511      fprintf(stderr,"IP:%01d PC:%02d X:%04d E:%03d P:%03d Pc:%03d ",m_interp_period, m_PC,
2512         m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
2513      //fprintf(stderr,"X:%04d E:%03d P:%03d Pc:%03d ", m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
2514      for (i=0; i<10; i++)
2515         fprintf(stderr,"K%d:%04d ", i+1, m_current_k[i]);
2516      fprintf(stderr,"Out:%06d", this_sample);
2517      fprintf(stderr,"\n");
2518#endif
2519      // next, force result to 14 bits (since its possible that the addition at the final (k1) stage of the lattice overflowed)
2520      while (this_sample > 16383) this_sample -= 32768;
2521      while (this_sample < -16384) this_sample += 32768;
2522      if (!m_digital_select) // analog SPK pin output is only 8 bits, with clipping
2523         buffer[buf_count] = clip_analog(this_sample);
2524      else // digital I/O pin output is 12 bits
2525      {
2526#ifdef ALLOW_4_LSB
2527         // input:  ssss ssss ssss ssss ssnn nnnn nnnn nnnn
2528         // N taps:                       ^                 = 0x2000;
2529         // output: ssss ssss ssss ssss snnn nnnn nnnn nnnN
2530         buffer[buf_count] = (this_sample<<1)|((this_sample&0x2000)>>13);
2531#else
2532         this_sample &= ~0xF;
2533         // input:  ssss ssss ssss ssss ssnn nnnn nnnn 0000
2534         // N taps:                       ^^ ^^^            = 0x3E00;
2535         // output: ssss ssss ssss ssss snnn nnnn nnnN NNNN
2536         buffer[buf_count] = (this_sample<<1)|((this_sample&0x3E00)>>9);
2537#endif
2538      }
2539
2540      // Update all counts
2541      m_subcycle++;
2542      if ((m_subcycle == 2) && (m_PC == 12))
2543      {
2544         m_subcycle = m_subc_reload;
2545         m_PC = 0;
2546         m_interp_period++;
2547         m_interp_period &= 0x7;
2548      }
2549      else if (m_subcycle == 3)
2550      {
2551         m_subcycle = m_subc_reload;
2552         m_PC++;
2553      }
2554      // Circuit 412 in the patent ensures that when INHIBIT is true,
2555      // during the period from IP=7 PC=12 T12, to IP=0 PC=12 T12, the pitch
2556      // count is forced to 0; since the initial stop happens right before
2557      // the switch to IP=0 PC=0 and this code is located after the switch would
2558      // happen, we check for ip=0 inhibit=1, which covers that whole range.
2559      // The purpose of Circuit 412 is to prevent a spurious click caused by
2560      // the voiced source being fed to the filter before all the values have
2561      // been updated during ip=0 when interpolation was inhibited.
2562
2563      m_pitch_count++;
2564      if (m_pitch_count >= m_current_pitch) m_pitch_count = 0;
2565      if ((m_interp_period == 0) && m_inhibit) m_pitch_count = 0;
2566      m_pitch_count &= 0x1FF;
2567      buf_count++;
2568      size--;
2569   }
2570
2571empty:
2572
2573   while (size > 0)
2574   {
2575      m_subcycle++;
2576      if ((m_subcycle == 2) && (m_PC == 12))
2577      {
2578         m_subcycle = m_subc_reload;
2579         m_PC = 0;
2580         m_interp_period++;
2581         m_interp_period &= 0x7;
2582      }
2583      else if (m_subcycle == 3)
2584      {
2585         m_subcycle = m_subc_reload;
2586         m_PC++;
2587      }
2588      buffer[buf_count] = -1;   // should be just -1; actual chip outputs -1 every idle sample; (cf note in data sheet, p 10, table 4)
2589      buf_count++;
2590      size--;
2591   }
2592}
2593
2594/******************************************************************************
2595    lattice_filter -- executes one 'full run' of the lattice filter on a
2596    specific byte of excitation data, and specific values of all the current k
2597    constants,  and returns the resulting sample.
2598******************************************************************************/
2599
2600INT32 tms52xx_device::lattice_filter()
2601{
2602   // Lattice filter here */
2603   // Aug/05/07: redone as unrolled loop, for clarity - LN
2604   // Originally Copied verbatim from table I in US patent 4,209,804, now updated
2605   // to be in same order as the actual chip does it, not that it matters.
2606   // notation equivalencies from table:
2607   //      Yn(i) == m_u[n-1]
2608   //      Kn = m_current_k[n-1]
2609   //      bn = m_x[n-1]
2610
2611   m_u[10] = matrix_multiply(m_previous_energy, (m_excitation_data<<6));  //Y(11)
2612   m_u[9] = m_u[10] - matrix_multiply(m_current_k[9], m_x[9]);
2613   m_u[8] = m_u[9] - matrix_multiply(m_current_k[8], m_x[8]);
2614   m_u[7] = m_u[8] - matrix_multiply(m_current_k[7], m_x[7]);
2615   m_u[6] = m_u[7] - matrix_multiply(m_current_k[6], m_x[6]);
2616   m_u[5] = m_u[6] - matrix_multiply(m_current_k[5], m_x[5]);
2617   m_u[4] = m_u[5] - matrix_multiply(m_current_k[4], m_x[4]);
2618   m_u[3] = m_u[4] - matrix_multiply(m_current_k[3], m_x[3]);
2619   m_u[2] = m_u[3] - matrix_multiply(m_current_k[2], m_x[2]);
2620   m_u[1] = m_u[2] - matrix_multiply(m_current_k[1], m_x[1]);
2621   m_u[0] = m_u[1] - matrix_multiply(m_current_k[0], m_x[0]);
2622   m_x[9] = m_x[8] + matrix_multiply(m_current_k[8], m_u[8]);
2623   m_x[8] = m_x[7] + matrix_multiply(m_current_k[7], m_u[7]);
2624   m_x[7] = m_x[6] + matrix_multiply(m_current_k[6], m_u[6]);
2625   m_x[6] = m_x[5] + matrix_multiply(m_current_k[5], m_u[5]);
2626   m_x[5] = m_x[4] + matrix_multiply(m_current_k[4], m_u[4]);
2627   m_x[4] = m_x[3] + matrix_multiply(m_current_k[3], m_u[3]);
2628   m_x[3] = m_x[2] + matrix_multiply(m_current_k[2], m_u[2]);
2629   m_x[2] = m_x[1] + matrix_multiply(m_current_k[1], m_u[1]);
2630   m_x[1] = m_x[0] + matrix_multiply(m_current_k[0], m_u[0]);
2631   m_x[0] = m_u[0];
2632   m_previous_energy = m_current_energy;
2633#ifdef DEBUG_LATTICE
2634
2635   int i;
2636   fprintf(stderr,"V:%04d ", m_u[10]);
2637   for (i = 9; i >= 0; i--)
2638   {
2639      fprintf(stderr,"Y%d:%04d ", i+1, m_u[i]);
2640      fprintf(stderr,"b%d:%04d ", i+1, m_x[i]);
2641      if ((i % 5) == 0) fprintf(stderr,"\n");
2642   }
2643#endif
2644   return m_u[0];
2645}
2646
2647/**********************************************************************************************
2648    data_write -- handle a write to the TMS5220
2649***********************************************************************************************/
2650
2651void tms52xx_device::data_write(int data)
2652{
2653#ifdef DEBUG_DUMP_INPUT_DATA
2654   fprintf(stdout, "%c",data);
2655#endif
2656   if (m_speak_external) // If we're in speak external mode
2657   {
2658      /* add this byte to the FIFO */
2659      if (m_fifo_count < FIFO_SIZE)
2660      {
2661         m_fifo[m_fifo_tail] = data;
2662         m_fifo_tail = (m_fifo_tail + 1) % FIFO_SIZE;
2663         m_fifo_count++;
2664#ifdef DEBUG_FIFO
2665         logerror("tms52xx: data_write: Added byte to FIFO (current count=%2d)\n", m_fifo_count);
2666#endif
2667         update_status_and_ints();
2668         if ((!m_talk_status) && (!m_buffer_low)) // we just unset buffer low with that last write, and talk status *was* zero...
2669         {
2670            int i;
2671#ifdef DEBUG_FIFO
2672            logerror("tms52xx: data_write triggered talk status to go active!\n");
2673#endif
2674            // ...then we now have enough bytes to start talking; clear out
2675            // the new frame parameters (it will become old frame just before the first call to parse_frame())
2676            // TODO: the 3 lines below (and others) are needed for victory
2677            // to not fail its selftest due to a sample ending too late, may require additional investigation
2678            m_subcycle = m_subc_reload;
2679            m_PC = 0;
2680            m_interp_period = reload_table[m_tms5220c_rate & 0x3]; // is this correct? should this be always 7 instead, so that the new frame is loaded quickly?
2681            m_new_frame_energy_idx = 0;
2682            m_new_frame_pitch_idx = 0;
2683
2684            for (i = 0; i < 4; i++)
2685               m_new_frame_k_idx[i] = 0;
2686            for (i = 4; i < 7; i++)
2687               m_new_frame_k_idx[i] = 0xF;
2688            for (i = 7; i < m_coeff->num_k; i++)
2689               m_new_frame_k_idx[i] = 0x7;
2690            m_talk_status = m_speaking_now = true;
2691         }
2692      }
2693      else
2694      {
2695#ifdef DEBUG_FIFO
2696         logerror("tms52xx: data_write: Ran out of room in the tms52xx FIFO! this should never happen!\n");
2697         // at this point, /READY should remain HIGH/inactive until the fifo has at least one byte open in it.
2698#endif
2699      }
2700
2701
2702   }
2703   else //(! m_speak_external)
2704      /* R Nabet : we parse commands at once.  It is necessary for such commands as read. */
2705      process_command(data);
2706}
2707
2708/******************************************************************************
2709    process_command -- extract a byte from the FIFO and interpret it as a command
2710*******************************************************************************/
2711
2712void tms52xx_device::process_command(unsigned char cmd)
2713{
2714#ifdef DEBUG_COMMAND_DUMP
2715   fprintf(stderr,"process_command called with parameter %02X\n",cmd);
2716#endif
2717   // parse the command
2718   switch (cmd & 0x70)
2719   {
2720   case 0x10 : // read byte
2721      if (!m_talk_status) // TALKST must be clear for RDBY
2722      {
2723         if (m_schedule_dummy_read)
2724         {
2725            m_schedule_dummy_read = false;
2726            (void)m_read_mem(1);
2727         }
2728         m_data_register = m_read_mem(8);   // read one byte from speech ROM...
2729         m_RDB_flag = true;
2730      }
2731      break;
2732
2733   case 0x00:
2734   case 0x20: // set rate (tms5220c only), otherwise NOP
2735      if (m_variant == SUBTYPE_TMS5220C)
2736      {
2737         m_tms5220c_rate = cmd & 0x0F;
2738      }
2739      break;
2740
2741   case 0x30: // read and branch
2742      if (!m_talk_status) // TALKST must be clear for RB
2743      {
2744#ifdef VERBOSE
2745         logerror("tms5520: read and branch command received\n");
2746#endif
2747         m_RDB_flag = false;
2748         m_read_and_branch(0, 0);
2749      }
2750      break;
2751
2752   case 0x40 : // load address
2753      if (!m_talk_status) // TALKST must be clear for LA
2754      {
2755         // tms5220 data sheet says that if we load only one 4-bit nibble, it won't work.
2756         // This code does not care about this.
2757         m_load_address(0, cmd & 0x0f);
2758         m_schedule_dummy_read = true;
2759      }
2760      break;
2761
2762   case 0x50:   // speak
2763      if (m_schedule_dummy_read)
2764      {
2765         m_schedule_dummy_read = false;
2766         (void)m_read_mem(1);
2767      }
2768      m_speaking_now = true;
2769      m_speak_external = false;
2770      m_talk_status = true;  // start immediately
2771      // clear out variables before speaking
2772      // TODO: similar to the victory case described above, but for VSM speech
2773      m_subcycle = m_subc_reload;
2774      m_PC = 0;
2775      m_interp_period = reload_table[m_tms5220c_rate & 0x3];
2776      m_new_frame_energy_idx = 0;
2777      m_new_frame_pitch_idx = 0;
2778
2779      int i;
2780      for (i = 0; i < 4; i++)
2781         m_new_frame_k_idx[i] = 0;
2782      for (i = 4; i < 7; i++)
2783         m_new_frame_k_idx[i] = 0xF;
2784      for (i = 7; i < m_coeff->num_k; i++)
2785         m_new_frame_k_idx[i] = 0x7;
2786      break;
2787
2788   case 0x60: // speak external
2789      if (!m_talk_status) // TALKST must be clear for SPKEXT
2790      {
2791         //SPKEXT going active activates SPKEE which clears the fifo
2792         m_fifo_head = m_fifo_tail = 0;
2793         m_fifo_count = m_fifo_bits_taken = 0;
2794         m_speak_external = true;
2795         m_RDB_flag = false;
2796      }
2797      break;
2798
2799   case 0x70: // reset
2800      if (m_schedule_dummy_read)
2801      {
2802         m_schedule_dummy_read = false;
2803         (void)m_read_mem(1);
2804      }
2805      device_reset();
2806      break;
2807   }
2808
2809   // update the buffer low state
2810   update_status_and_ints();
2811}
2812
2813/******************************************************************************
2814    parse_frame -- parse a new frame's worth of data; returns 0 if not
2815    enough bits in buffer
2816*******************************************************************************/
2817
2818void tms52xx_device::parse_frame()
2819{
2820   int indx, i, rep_flag;
2821
2822   // We actually don't care how many bits are left in the fifo here; the
2823   // frame subpart will be processed normally, and any bits extracted 'past
2824   // the end' of the fifo will be read as zeroes; the fifo being emptied will
2825   // set the /BE latch which will halt speech exactly as if a stop frame had
2826   // been encountered (instead of whatever partial frame was read); the same
2827   // exact circuitry is used for both on the real chip, see us patent 4335277
2828   // sheet 16, gates 232a (decode stop frame) and 232b (decode /BE plus DDIS
2829   // (decode disable) which is active during speak external).
2830
2831   // if the chip is a tms5220C, and the rate mode is set to that each frame (0x04 bit set)
2832   // has a 2 bit rate preceding it, grab two bits here and store them as the rate;
2833   if ((m_variant == SUBTYPE_TMS5220C) && (m_tms5220c_rate & 0x04))
2834   {
2835      indx = extract_bits(2);
2836#ifdef DEBUG_PARSE_FRAME_DUMP
2837      printbits(indx,2);
2838      fprintf(stderr," ");
2839#endif
2840      m_interp_period = reload_table[indx];
2841   }
2842   else // non-5220C and 5220C in fixed rate mode
2843      m_interp_period = reload_table[m_tms5220c_rate & 0x3];
2844
2845   update_status_and_ints();
2846   if (!m_talk_status) goto ranout;
2847
2848   // attempt to extract the energy index
2849   m_new_frame_energy_idx = extract_bits(m_coeff->energy_bits);
2850#ifdef DEBUG_PARSE_FRAME_DUMP
2851   printbits(m_new_frame_energy_idx,m_coeff->energy_bits);
2852   fprintf(stderr," ");
2853#endif
2854   update_status_and_ints();
2855   if (!m_talk_status) goto ranout;
2856   // if the energy index is 0 or 15, we're done
2857   if ((m_new_frame_energy_idx == 0) || (m_new_frame_energy_idx == 15))
2858      return;
2859
2860   // attempt to extract the repeat flag
2861   rep_flag = extract_bits(1);
2862#ifdef DEBUG_PARSE_FRAME_DUMP
2863   printbits(rep_flag, 1);
2864   fprintf(stderr," ");
2865#endif
2866
2867   // attempt to extract the pitch
2868   m_new_frame_pitch_idx = extract_bits(m_coeff->pitch_bits);
2869#ifdef DEBUG_PARSE_FRAME_DUMP
2870   printbits(m_new_frame_pitch_idx, m_coeff->pitch_bits);
2871   fprintf(stderr," ");
2872#endif
2873   update_status_and_ints();
2874   if (!m_talk_status) goto ranout;
2875   // if this is a repeat frame, just do nothing, it will reuse the
2876   // old coefficients's
2877   if (rep_flag) return;
2878
2879   // extract first 4 K coefficients
2880   for (i = 0; i < 4; i++)
2881   {
2882      m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]);
2883#ifdef DEBUG_PARSE_FRAME_DUMP
2884      printbits(m_new_frame_k_idx[i], m_coeff->kbits[i]);
2885      fprintf(stderr," ");
2886#endif
2887      update_status_and_ints();
2888      if (!m_talk_status) goto ranout;
2889   }
2890
2891   // if the pitch index was zero, we only need 4 K's...
2892   if (m_new_frame_pitch_idx == 0)
2893   {
2894      // and the rest of the coefficients are zeroed, but that's done in the generator code
2895      return;
2896   }
2897
2898   // If we got here, we need the remaining 6 K's
2899   for (i = 4; i < m_coeff->num_k; i++)
2900   {
2901      m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]);
2902#ifdef DEBUG_PARSE_FRAME_DUMP
2903      printbits(m_new_frame_k_idx[i], m_coeff->kbits[i]);
2904      fprintf(stderr," ");
2905#endif
2906      update_status_and_ints();
2907      if (!m_talk_status) goto ranout;
2908   }
2909#ifdef VERBOSE
2910   if (m_speak_external)
2911      logerror("tms52xx: Parsed a frame successfully in FIFO - %d bits remaining\n", (m_fifo_count*8)-(m_fifo_bits_taken));
2912   else
2913      logerror("tms52xx: Parsed a frame successfully in ROM\n");
2914#endif
2915   return;
2916
2917   ranout:
2918#ifdef DEBUG_FRAME_ERRORS
2919   logerror("tms52xx: Ran out of bits on a parse!\n");
2920#endif
2921   return;
2922}
2923
2924/**********************************************************************************************
2925
2926     update_status_and_ints -- check to see if the various flags should be on or off
2927     Description of flags, and their position in the status register:
2928      From the data sheet:
2929        bit D0(bit 7) = TS - Talk Status is active (high) when the VSP is processing speech data.
2930                Talk Status goes active at the initiation of a Speak command or after nine
2931                bytes of data are loaded into the FIFO following a Speak External command. It
2932                goes inactive (low) when the stop code (Energy=1111) is processed, or
2933                immediately by a buffer empty condition or a reset command.
2934        bit D1(bit 6) = BL - Buffer Low is active (high) when the FIFO buffer is more than half empty.
2935                Buffer Low is set when the "Last-In" byte is shifted down past the half-full
2936                boundary of the stack. Buffer Low is cleared when data is loaded to the stack
2937                so that the "Last-In" byte lies above the half-full boundary and becomes the
2938                eighth data byte of the stack.
2939        bit D2(bit 5) = BE - Buffer Empty is active (high) when the FIFO buffer has run out of data
2940                while executing a Speak External command. Buffer Empty is set when the last bit
2941                of the "Last-In" byte is shifted out to the Synthesis Section. This causes
2942                Talk Status to be cleared. Speed is terminated at some abnormal point and the
2943                Speak External command execution is terminated.
2944
2945***********************************************************************************************/
2946
2947void tms52xx_device::update_status_and_ints()
2948{
2949   // update flags and set ints if needed
2950   update_ready_state();
2951
2952   // BL is set if neither byte 9 nor 8 of the fifo are in use; this
2953   // translates to having fifo_count (which ranges from 0 bytes in use to 16
2954   // bytes used) being less than or equal to 8. Victory/Victorba depends on this.
2955   if (m_fifo_count <= 8)
2956   {
2957      // generate an interrupt if necessary; if /BL was inactive and is now active, set int.
2958      if (!m_buffer_low) set_interrupt_state(1);
2959      m_buffer_low = true;
2960   }
2961   else
2962      m_buffer_low = false;
2963
2964   // BE is set if neither byte 15 nor 14 of the fifo are in use; this
2965   // translates to having fifo_count equal to exactly 0 */
2966   if (m_fifo_count == 0)
2967   {
2968      // generate an interrupt if necessary; if /BE was inactive and is now active, set int.
2969      if (!m_buffer_empty) set_interrupt_state(1);
2970      m_buffer_empty = true;
2971   }
2972   else
2973      m_buffer_empty = false;
2974
2975   // TS is talk status and is set elsewhere in the fifo parser and in
2976   // the SPEAK command handler; however, if /BE is true during speak external
2977   // mode, it is immediately unset here.
2978   if (m_speak_external && m_buffer_empty)
2979   {
2980      // generate an interrupt: /TS was active, and is now inactive.
2981      if (m_talk_status)
2982      {
2983         m_talk_status = m_speak_external = false;
2984         set_interrupt_state(1);
2985      }
2986   }
2987   // Note that TS being unset will also generate an interrupt when a STOP
2988   // frame is encountered; this is handled in the sample generator code and not here */
2989}
2990
2991/******************************************************************************
2992    extract_bits -- extract a specific number of bits from the current input stream (FIFO or VSM)
2993*******************************************************************************/
2994
2995int tms52xx_device::extract_bits(int count)
2996{
2997   int val = 0;
2998
2999   if (m_speak_external)
3000   {
3001      // extract from FIFO
3002      while (count--)
3003      {
3004         val = (val << 1) | ((m_fifo[m_fifo_head] >> m_fifo_bits_taken) & 1);
3005         m_fifo_bits_taken++;
3006         if (m_fifo_bits_taken >= 8)
3007         {
3008            m_fifo_count--;
3009            m_fifo[m_fifo_head] = 0; // zero the newly depleted fifo head byte
3010            m_fifo_head = (m_fifo_head + 1) % FIFO_SIZE;
3011            m_fifo_bits_taken = 0;
3012            update_status_and_ints();
3013         }
3014      }
3015   }
3016   else
3017   {
3018      // extract from VSM (speech ROM)
3019      val = m_read_mem(count);
3020   }
3021   return val;
3022}
3023
3024/******************************************************************************
3025    status_read -- read status or data from the TMS5220
3026*******************************************************************************/
3027
3028int tms52xx_device::status_read()
3029{
3030   if (m_RDB_flag)
3031   {   // if last command was read, return data register
3032      m_RDB_flag = false;
3033      return m_data_register;
3034   }
3035   else
3036   {   // read status
3037      // clear the interrupt pin on status read
3038      set_interrupt_state(0);
3039#ifdef DEBUG_PIN_READS
3040      logerror("tms52xx: Status read: TS=%d BL=%d BE=%d\n", m_talk_status, m_buffer_low, m_buffer_empty);
3041#endif
3042
3043      int retvalue = 0;
3044      if (m_talk_status) retvalue |= 0x80;
3045      if (m_buffer_low) retvalue |= 0x40;
3046      if (m_buffer_empty) retvalue |= 0x20;
3047      return retvalue;
3048   }
3049}
3050
3051/******************************************************************************
3052    ready_read -- returns the ready state of the TMS5220
3053*******************************************************************************/
3054
3055inline bool tms52xx_device::ready_read()
3056{
3057#ifdef DEBUG_PIN_READS
3058   logerror("tms52xx: ready_read: ready pin read, io_ready is %d, fifo count is %d\n", m_io_ready, m_fifo_count);
3059#endif
3060   return ((m_fifo_count < FIFO_SIZE)||(!m_speak_external)) && m_io_ready;
3061}
3062
3063/******************************************************************************
3064    int_read -- returns the interrupt state of the TMS5220
3065*******************************************************************************/
3066
3067inline int tms52xx_device::int_read()
3068{
3069#ifdef DEBUG_PIN_READS
3070   logerror("tms52xx: int_read: irq pin read, state is %d\n", m_irq_pin);
3071#endif
3072   return m_irq_pin;
3073}
3074
3075/******************************************************************************
3076    cycles_to_ready -- returns the number of cycles until ready is asserted
3077    NOTE: this function is deprecated and is known to be VERY inaccurate.
3078    Use at your own peril!
3079*******************************************************************************/
3080
3081int tms52xx_device::cycles_to_ready()
3082{
3083   int answer;
3084
3085   if (ready_read()) answer = 0;
3086   else
3087   {
3088      int val;
3089      int samples_per_frame = (m_subc_reload!=0)? 200:304; // either (13 A cycles + 12 B cycles) * 8 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 8 interps for SPKSLOW
3090      int current_sample = ((m_PC * (3-m_subc_reload)) + (((m_subc_reload!=0)? 38:25) * m_interp_period));
3091      answer = samples_per_frame - current_sample + 8;
3092
3093      // total number of bits available in current byte is (8 - tms->fifo_bits_taken)
3094      // if more than 4 are available, we need to check the energy
3095      if (m_fifo_bits_taken < 4)
3096      {
3097         // read energy
3098         val = (m_fifo[m_fifo_head] >> m_fifo_bits_taken) & 0xf;
3099         if (val == 0)
3100            // 0 -> silence frame: we will only read 4 bits, and we will
3101            // therefore need to read another frame before the FIFO is not
3102            // full any more
3103            answer += 200;
3104         // 15 -> stop frame, we will only read 4 bits, but the FIFO will
3105         // we cleared
3106         //otherwise, we need to parse the repeat flag (1 bit) and the
3107         // pitch (6 bits), so everything will be OK.
3108      }
3109   }
3110   return answer;
3111}
3112
3113/******************************************************************************
3114    True timing
3115*******************************************************************************/
3116
3117void tms52xx_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
3118{
3119   if (param)
3120   {
3121      switch (m_rs_ws)
3122      {
3123      case 0x02:
3124         // Write
3125         // bring up to date first
3126#ifdef DEBUG_IO_READY
3127         logerror("tms52xx: Serviced write: %02x\n", tms->write_latch);
3128         //fprintf(stderr, "Processed write data: %02X\n", tms->write_latch);
3129#endif
3130         m_stream->update();
3131         data_write(m_write_latch);
3132          break;
3133      case 0x01:
3134         // Read
3135         // bring up to date first
3136         m_stream->update();
3137         m_read_latch = status_read();
3138         break;
3139      case 0x03:
3140         // High Impedance
3141      case 0x00:
3142         // illegal
3143         break;
3144      }
3145   }
3146   m_io_ready = param;
3147   update_ready_state();
3148}
3149
3150/*****************************************************
3151    /RS line write handler
3152*****************************************************/
3153
3154WRITE_LINE_MEMBER( tms52xx_device::rsq_w )
3155{
3156   UINT8 new_val;
3157
3158   m_true_timing = true;
3159   state &= 0x01;
3160#ifdef DEBUG_RS_WS
3161   logerror("tms52xx: /RS written with data: %d\n", state);
3162#endif
3163   new_val = (m_rs_ws & 0x01) | (state<<1);
3164   if (new_val != m_rs_ws)
3165   {
3166      m_rs_ws = new_val;
3167      if (new_val == 0)
3168      {
3169         if (m_variant == SUBTYPE_TMS5220C)
3170            reset();
3171#ifdef DEBUG_RS_WS
3172         else
3173            // illegal
3174            logerror("tms52xx: illegal line setting /RS=0 and /WS=0\n");
3175#endif
3176         return;
3177      }
3178      else if (new_val == 3)
3179      {
3180         // high impedance
3181         m_read_latch = 0xff;
3182         return;
3183      }
3184      if (state)
3185      {
3186         // low to high
3187      }
3188      else
3189      {
3190         // high to low - schedule ready cycle
3191#ifdef DEBUG_RS_WS
3192         logerror("tms52xx: Scheduling ready cycle for /RS...\n");
3193#endif
3194         // upon /RS being activated, /READY goes inactive after 100 nsec from
3195         // data sheet, through 3 asynchronous gates on patent. This is effectively
3196         // within one clock, so we immediately set io_ready to 0 and activate the callback. */
3197         m_io_ready = 0;
3198         update_ready_state();
3199         // How long does /READY stay inactive, when /RS is pulled low?
3200         // I believe its almost always ~16 clocks (25 usec at 800khz as shown on the datasheet)
3201         m_ready_timer->adjust(attotime::from_hz(clock()/16));
3202      }
3203   }
3204}
3205
3206/*****************************************************
3207    /WS line write handler
3208*****************************************************/
3209
3210WRITE_LINE_MEMBER( tms52xx_device::wsq_w )
3211{
3212   UINT8 new_val;
3213
3214   m_true_timing = true;
3215   state &= 0x01;
3216#ifdef DEBUG_RS_WS
3217   logerror("tms52xx: /WS written with data: %d\n", state);
3218#endif
3219   new_val = (m_rs_ws & 0x02) | (state<<0);
3220   if (new_val != m_rs_ws)
3221   {
3222      m_rs_ws = new_val;
3223      if (new_val == 0)
3224      {
3225         if (m_variant == SUBTYPE_TMS5220C)
3226            reset();
3227#ifdef DEBUG_RS_WS
3228         else
3229            // illegal
3230            logerror("tms52xx: illegal line setting /RS=0 and /WS=0\n");
3231#endif
3232         return;
3233      }
3234      else if ( new_val == 3)
3235      {
3236         // high impedance
3237         m_read_latch = 0xff;
3238         return;
3239      }
3240      if (state)
3241      {
3242         // low to high
3243      }
3244      else
3245      {
3246         // high to low - schedule ready cycle
3247#ifdef DEBUG_RS_WS
3248         logerror("tms52xx: Scheduling ready cycle for /WS...\n");
3249#endif
3250         // upon /WS being activated, /READY goes inactive after 100 nsec
3251         // from data sheet, through 3 asynchronous gates on patent.
3252         // This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback.
3253         m_io_ready = 0;
3254         update_ready_state();
3255         // Now comes the complicated part: long does /READY stay inactive
3256         // when /WS is pulled low? This depends ENTIRELY on the command written,
3257         // or whether the chip is in speak external mode or not...
3258         // Speak external mode: ~16 cycles
3259         // Command Mode:
3260         // SPK: ? cycles
3261         // SPKEXT: ? cycles
3262         // RDBY: between 60 and 140 cycles
3263         // RB: ? cycles (80?)
3264         // RST: between 60 and 140 cycles
3265         // SET RATE (5220C only): ? cycles (probably ~16)
3266
3267         // TODO: actually HANDLE the timing differences! currently just assuming always 16 cycles
3268         m_ready_timer->adjust(attotime::from_hz(clock()/16));
3269      }
3270   }
3271}
3272
3273/*****************************************************************************
3274    write -- write data to the sound chip
3275*******************************************************************************/
3276
3277WRITE8_MEMBER( tms52xx_device::write )
3278{
3279#ifdef DEBUG_RS_WS
3280   logerror("tms52xx: write data %02x\n", data);
3281#endif
3282   if (!m_true_timing)
3283   {
3284      // bring up to date first
3285      m_stream->update();
3286      data_write(data);
3287   }
3288   else
3289   {
3290      // actually in a write?
3291#ifdef DEBUG_RS_WS
3292      if (!(m_rs_ws == 0x02))
3293         logerror("tms52xx: write data written outside ws, status: %02x!\n", m_rs_ws);
3294#endif
3295      m_write_latch = data;
3296   }
3297}
3298
3299/******************************************************************************
3300    read -- read status or data from the sound chip
3301*******************************************************************************/
3302
3303READ8_MEMBER( tms52xx_device::read )
3304{
3305   if (!m_true_timing)
3306   {
3307      // bring up-to-date first
3308      m_stream->update();
3309      return status_read();
3310   }
3311   else
3312   {
3313      // actually in a read?
3314      if (m_rs_ws == 0x01)
3315         return m_read_latch;
3316#ifdef DEBUG_RS_WS
3317      else
3318         logerror("tms52xx: data read outside rs!\n");
3319#endif
3320      return 0xff;
3321   }
3322}
3323
3324/*******************************************************************************
3325    ready -- return the not ready status from the sound chip
3326*******************************************************************************/
3327
3328READ_LINE_MEMBER( tms52xx_device::readyq )
3329{
3330   // bring up-to-date first
3331   m_stream->update();
3332   return !ready_read();
3333}
3334
3335
3336/******************************************************************************
3337    time_to_ready -- return the time in seconds until the
3338    ready line is asserted
3339*******************************************************************************/
3340
3341double tms52xx_device::time_to_ready()
3342{
3343   double cycles;
3344
3345   // bring up-to-date
3346   m_stream->update();
3347   cycles = cycles_to_ready();
3348   return cycles * 80.0 / m_clock;
3349}
3350
3351/******************************************************************************
3352    intq -- return the interrupt status from the sound chip
3353******************************************************************************/
3354
3355READ_LINE_MEMBER( tms52xx_device::intq )
3356{
3357   // bring up-to-date first
3358   m_stream->update();
3359   return !int_read();
3360}
3361
3362void tms52xx_device::register_for_save_states()
3363{
3364   save_item(NAME(m_fifo));
3365   save_item(NAME(m_fifo_head));
3366   save_item(NAME(m_fifo_tail));
3367   save_item(NAME(m_fifo_count));
3368   save_item(NAME(m_fifo_bits_taken));
3369
3370   save_item(NAME(m_speaking_now));
3371   save_item(NAME(m_speak_external));
3372   save_item(NAME(m_talk_status));
3373   save_item(NAME(m_buffer_low));
3374   save_item(NAME(m_buffer_empty));
3375   save_item(NAME(m_irq_pin));
3376   save_item(NAME(m_ready_pin));
3377
3378   save_item(NAME(m_OLDE));
3379   save_item(NAME(m_OLDP));
3380
3381   save_item(NAME(m_new_frame_energy_idx));
3382   save_item(NAME(m_new_frame_pitch_idx));
3383   save_item(NAME(m_new_frame_k_idx));
3384#ifdef PERFECT_INTERPOLATION_HACK
3385   save_item(NAME(m_old_frame_energy_idx));
3386   save_item(NAME(m_old_frame_pitch_idx));
3387   save_item(NAME(m_old_frame_k_idx));
3388#endif
3389   save_item(NAME(m_current_energy));
3390   save_item(NAME(m_current_pitch));
3391   save_item(NAME(m_current_k));
3392
3393   save_item(NAME(m_target_energy));
3394   save_item(NAME(m_target_pitch));
3395   save_item(NAME(m_target_k));
3396
3397   save_item(NAME(m_previous_energy));
3398
3399   save_item(NAME(m_subcycle));
3400   save_item(NAME(m_subc_reload));
3401   save_item(NAME(m_PC));
3402   save_item(NAME(m_interp_period));
3403   save_item(NAME(m_inhibit));
3404   save_item(NAME(m_tms5220c_rate));
3405   save_item(NAME(m_pitch_count));
3406
3407   save_item(NAME(m_u));
3408   save_item(NAME(m_x));
3409
3410   save_item(NAME(m_RNG));
3411   save_item(NAME(m_excitation_data));
3412
3413   save_item(NAME(m_schedule_dummy_read));
3414   save_item(NAME(m_data_register));
3415   save_item(NAME(m_RDB_flag));
3416   save_item(NAME(m_digital_select));
3417
3418   save_item(NAME(m_io_ready));
3419}
3420
3421
3422const device_type TMS5220N = &device_creator<tms5220n_device>;
3423const device_type TMS5220CN = &device_creator<tms5220cn_device>;
3424const device_type TMC0285N = &device_creator<tmc0285n_device>;
3425const device_type TMS5200N = &device_creator<tms5200n_device>;
3426
src/emu/sound/tms5220.h
r15499r15500
55
66#include "devlegcy.h"
77
8#define FIFO_SIZE 16
89
910/* clock rate = 80 * output sample rate,     */
1011/* usually 640000 for 8000 Hz sample rate or */
r15499r15500
4748DECLARE_LEGACY_SOUND_DEVICE(TMS5200, tms5200);
4849
4950
51/***************************************************************************
52        New class implementation
53        Michael Zapf, June 2012
54***************************************************************************/
55
56extern const device_type TMS5220N;
57extern const device_type TMS5220CN;
58extern const device_type TMC0285N;
59extern const device_type TMS5200N;
60
61
62typedef struct _tms52xx_config
63{
64   devcb_write_line      irq_func;               // IRQ callback function, active low, i.e. state=0  (TODO: change to ASSERT/CLEAR)
65   devcb_write_line      readyq_func;            // Ready callback function, active low, i.e. state=0
66
67   devcb_read8            read_mem;               // speech ROM read callback
68   devcb_write8         load_address;            // speech ROM load address callback
69   devcb_write8         read_and_branch;         // speech ROM read and branch callback
70
71} tms52xx_config;
72
73// Change back from 5220n to 5220 when all client drivers will be converted
74class tms52xx_device : public device_t, public device_sound_interface
75{
76public:
77   tms52xx_device(const machine_config &mconfig, device_type type,  const char *name, const char *tag, const struct tms5100_coeffs* coeffs, const int var, device_t *owner, UINT32 clock);
78   void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
79   void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
80
81   DECLARE_WRITE_LINE_MEMBER( rsq_w );
82   DECLARE_WRITE_LINE_MEMBER( wsq_w );
83   DECLARE_WRITE8_MEMBER( write );
84   DECLARE_READ8_MEMBER( read );
85   DECLARE_READ_LINE_MEMBER( readyq );
86   DECLARE_READ_LINE_MEMBER( intq );
87
88   double time_to_ready();
89
90protected:
91   void device_start();
92   void device_reset();
93
94private:
95   // Methods
96   void set_interrupt_state(int state);
97   void register_for_save_states();
98   void update_ready_state();
99   void set_frequency(int frequency);
100   void process(INT16 *buffer, unsigned int size);
101   void data_write(int data);
102   void update_status_and_ints();
103   void parse_frame();
104
105   int extract_bits(int count);
106   int status_read();
107   int cycles_to_ready();
108   INT32 lattice_filter();
109   void process_command(unsigned char cmd);
110
111   inline bool ready_read();
112   inline int int_read();
113
114   // coefficient tables
115   const int m_variant;            // Variant of the 5xxx - see tms5110r.h
116
117   // coefficient tables
118   const struct tms5100_coeffs *m_coeff;
119
120   // callbacks
121   devcb_resolved_write_line   m_irq_func;
122   devcb_resolved_write_line   m_readyq_func;
123   devcb_resolved_read8      m_read_mem;
124   devcb_resolved_write8      m_load_address;
125   devcb_resolved_write8      m_read_and_branch;
126
127   // these contain data that describes the 128-bit data FIFO
128   UINT8   m_fifo[FIFO_SIZE];
129   UINT8   m_fifo_head;
130   UINT8   m_fifo_tail;
131   int      m_fifo_count;
132   int      m_fifo_bits_taken;
133
134   // these contain global status bits
135   bool   m_speaking_now;      // True only if actual speech is being generated right now. Is set when a speak vsm command happens OR when speak external happens and buffer low becomes nontrue; Is cleared when speech halts after the last stop frame or the last frame after talk status is otherwise cleared.
136   bool   m_speak_external;   // If 1, DDIS is 1, i.e. Speak External command in progress, writes go to FIFO.
137   bool   m_talk_status;      // If 1, TS status bit is 1, i.e. speak or speak external is in progress and we have not encountered a stop frame yet; talk_status differs from speaking_now in that speaking_now is set as soon as a speak or speak external command is started; talk_status does NOT go active until after 8 bytes are written to the fifo on a speak external command, otherwise the two are the same. TS is cleared by 3 things: 1. when a STOP command has just been processed as a new frame in the speech stream; 2. if the fifo runs out in speak external mode; 3. on power-up/during a reset command; When it gets cleared, speak_external is also cleared, an interrupt is generated, and speaking_now will be cleared when the next frame starts.
138   bool   m_buffer_low;      // If 1, FIFO has less than 8 bytes in it
139   bool   m_buffer_empty;      // If 1, FIFO is empty
140   int      m_irq_pin;         // state of the IRQ pin (output)
141   int      m_ready_pin;      // state of the READY pin (output)
142
143   // these contain data describing the current and previous voice frames
144#define M_OLD_FRAME_SILENCE_FLAG m_OLDE // 1 if E=0, 0 otherwise.
145#define M_OLD_FRAME_UNVOICED_FLAG m_OLDP // 1 if P=0 (unvoiced), 0 if voiced
146   bool   m_OLDE;
147   bool   m_OLDP;
148
149#define M_NEW_FRAME_STOP_FLAG (m_new_frame_energy_idx == 0xF)      // 1 if this is a stop (Energy = 0xF) frame
150#define M_NEW_FRAME_SILENCE_FLAG (m_new_frame_energy_idx == 0)   // ditto as above
151#define M_NEW_FRAME_UNVOICED_FLAG (m_new_frame_pitch_idx == 0)   // ditto as above
152   int      m_new_frame_energy_idx;
153   int      m_new_frame_pitch_idx;
154   int      m_new_frame_k_idx[10];
155
156   // these are all used to contain the current state of the sound generation
157#ifndef PERFECT_INTERPOLATION_HACK
158   INT16   m_current_energy;
159   INT16   m_current_pitch;
160   INT16   m_current_k[10];
161
162   INT16   m_target_energy;
163   INT16   m_target_pitch;
164   INT16   m_target_k[10];
165#else
166   int    m_old_frame_energy_idx;
167   int      m_old_frame_pitch_idx;
168   int      m_old_frame_k_idx[10];
169
170   INT32   m_current_energy;
171   INT32   m_current_pitch;
172   INT32   m_current_k[10];
173
174   INT32   m_target_energy;
175   INT32   m_target_pitch;
176   INT32   m_target_k[10];
177#endif
178
179   UINT16   m_previous_energy;   // needed for lattice filter to match patent
180   int    m_subcycle;         // contains the current subcycle for a given PC: 0 is A' (only used on SPKSLOW mode on 51xx), 1 is A, 2 is B
181   int    m_subc_reload;      // contains 1 for normal speech, 0 when SPKSLOW is active
182   int      m_PC;            // current parameter counter (what param is being interpolated), ranges from 0 to 12
183
184   // TODO/NOTE: the current interpolation period, counts 1,2,3,4,5,6,7,0 for divide by 8,8,8,4,4,4,2,1
185   int    m_interp_period;   // the current interpolation period
186   bool   m_inhibit;         // If 1, interpolation is inhibited until the DIV1 period
187   UINT8   m_tms5220c_rate;   // only relevant for tms5220C's multi frame rate feature; is the actual 4 bit value written on a 0x2* or 0x0* command
188   UINT16   m_pitch_count;      // pitch counter; provides chirp rom address
189
190   INT32   m_u[11];
191   INT32   m_x[10];
192
193   UINT16   m_RNG;      // the random noise generator configuration is: 1 + x + x^3 + x^4 + x^13
194   INT16   m_excitation_data;
195
196   // R Nabet : These have been added to emulate speech Roms
197   bool   m_schedule_dummy_read;   // set after each load address, so that next read operation is preceded by a dummy read
198   UINT8   m_data_register;      // data register, used by read command
199   bool   m_RDB_flag;            // whether we should read data register or status register
200
201   // io_ready: page 3 of the datasheet specifies that READY will be asserted until
202   // data is available or processed by the system.
203   int      m_io_ready;
204
205   // flag for "true" timing involving rs/ws
206   bool   m_true_timing;
207
208   // rsws - state, rs bit 1, ws bit 0
209   int      m_rs_ws;
210   UINT8   m_read_latch;
211   UINT8   m_write_latch;
212
213   // The TMS52xx has two different ways of providing output data: the
214   // analog speaker pin (which was usually used) and the Digital I/O pin.
215   // The internal DAC used to feed the analog pin is only 8 bits, and has the
216   // funny clipping/clamping logic, while the digital pin gives full 12? bit
217   // resolution of the output data.
218   // TODO: add a way to set/reset this other than the FORCE_DIGITAL define
219   bool         m_digital_select;
220
221   sound_stream   *m_stream;
222
223   emu_timer      *m_ready_timer;
224};
225
226class tms5220n_device : public tms52xx_device
227{
228public:
229   tms5220n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
230};
231
232class tms5220cn_device : public tms52xx_device
233{
234public:
235   tms5220cn_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
236};
237
238class tmc0285n_device : public tms52xx_device
239{
240public:
241   tmc0285n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
242};
243
244class tms5200n_device : public tms52xx_device
245{
246public:
247   tms5200n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
248};
249
250
50251#endif /* __TMS5220_H__ */

Previous 15994 Revisions Next


© 1998-2018 The MESS Team