trunk/src/mame/drivers/konamigx.c
| r29469 | r29470 | |
| 1077 | 1077 | /**********************************************************************************/ |
| 1078 | 1078 | /* Sound handling */ |
| 1079 | 1079 | |
| 1080 | | INTERRUPT_GEN_MEMBER(konamigx_state::tms_sync) |
| 1081 | | { |
| 1082 | | // DASP is synced to the LRCLK of one of the K054539s |
| 1083 | | if (m_sound_ctrl & 0x20) |
| 1084 | | m_dasp->sync_w(1); |
| 1085 | | } |
| 1086 | | |
| 1087 | 1080 | READ16_MEMBER(konamigx_state::tms57002_data_word_r) |
| 1088 | 1081 | { |
| 1089 | 1082 | return m_dasp->data_r(space, 0); |
| r29469 | r29470 | |
| 1617 | 1610 | |
| 1618 | 1611 | MCFG_CPU_ADD("dasp", TMS57002, 24000000/2) |
| 1619 | 1612 | MCFG_CPU_DATA_MAP(gxtmsmap) |
| 1620 | | MCFG_CPU_PERIODIC_INT_DRIVER(konamigx_state, tms_sync, 48000) |
| 1621 | 1613 | |
| 1622 | 1614 | MCFG_QUANTUM_TIME(attotime::from_hz(6000)) |
| 1623 | 1615 | |
| r29469 | r29470 | |
| 1658 | 1650 | /* sound hardware */ |
| 1659 | 1651 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 1660 | 1652 | |
| 1653 | MCFG_DEVICE_MODIFY("dasp") |
| 1654 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
| 1655 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
| 1656 | |
| 1661 | 1657 | MCFG_K056800_ADD("k056800", XTAL_18_432MHz) |
| 1662 | 1658 | MCFG_K056800_INT_HANDLER(INPUTLINE("soundcpu", M68K_IRQ_1)) |
| 1663 | 1659 | |
| 1664 | 1660 | MCFG_K054539_ADD("k054539_1", XTAL_18_432MHz, k054539_config) |
| 1665 | 1661 | MCFG_K054539_TIMER_HANDLER(WRITELINE(konamigx_state, k054539_irq_gen)) |
| 1666 | | |
| 1662 | MCFG_SOUND_ROUTE_EX(0, "dasp", 0.9, 0) |
| 1663 | MCFG_SOUND_ROUTE_EX(1, "dasp", 0.9, 1) |
| 1667 | 1664 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
| 1668 | 1665 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
| 1669 | 1666 | |
| 1670 | 1667 | MCFG_K054539_ADD("k054539_2", XTAL_18_432MHz, k054539_config) |
| 1668 | MCFG_SOUND_ROUTE_EX(0, "dasp", 0.9, 2) |
| 1669 | MCFG_SOUND_ROUTE_EX(1, "dasp", 0.9, 3) |
| 1671 | 1670 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
| 1672 | 1671 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
| 1673 | 1672 | MACHINE_CONFIG_END |
trunk/src/emu/sound.c
| r29469 | r29470 | |
| 94 | 94 | m_device.machine().save().save_item("stream", state_tag, outputnum, NAME(m_output[outputnum].m_gain)); |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | // Mark synchronous streams as such |
| 98 | m_synchronous = m_sample_rate == STREAM_SYNC; |
| 99 | if (m_synchronous) |
| 100 | { |
| 101 | m_sample_rate = 0; |
| 102 | m_sync_timer = m_device.machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sound_stream::sync_update), this)); |
| 103 | } |
| 104 | else |
| 105 | m_sync_timer = NULL; |
| 106 | |
| 97 | 107 | // force an update to the sample rates; this will cause everything to be recomputed |
| 98 | 108 | // and will generate the initial resample buffers for our inputs |
| 99 | 109 | recompute_sample_rate_data(); |
| r29469 | r29470 | |
| 284 | 294 | } |
| 285 | 295 | |
| 286 | 296 | |
| 297 | void sound_stream::sync_update(void *, INT32) |
| 298 | { |
| 299 | update(); |
| 300 | attotime time = m_device.machine().time(); |
| 301 | attoseconds_t next_edge = m_attoseconds_per_sample - (time.attoseconds % m_attoseconds_per_sample); |
| 302 | m_sync_timer->adjust(attotime(0, next_edge)); |
| 303 | } |
| 304 | |
| 305 | |
| 287 | 306 | //------------------------------------------------- |
| 288 | 307 | // output_since_last_update - return a pointer to |
| 289 | 308 | // the output buffer and the number of samples |
| r29469 | r29470 | |
| 447 | 466 | |
| 448 | 467 | void sound_stream::recompute_sample_rate_data() |
| 449 | 468 | { |
| 469 | if (m_synchronous) |
| 470 | { |
| 471 | m_sample_rate = 0; |
| 472 | // When synchronous, pick the sample rate for the inputs, if any |
| 473 | for (int inputnum = 0; inputnum < m_input.count(); inputnum++) |
| 474 | { |
| 475 | stream_input &input = m_input[inputnum]; |
| 476 | if (input.m_source != NULL) |
| 477 | { |
| 478 | if (!m_sample_rate) |
| 479 | m_sample_rate = input.m_source->m_stream->m_sample_rate; |
| 480 | else if (m_sample_rate != input.m_source->m_stream->m_sample_rate) |
| 481 | throw emu_fatalerror("Incompatible sample rates as input of a synchronous stream: %d and %d\n", m_sample_rate, input.m_source->m_stream->m_sample_rate); |
| 482 | } |
| 483 | } |
| 484 | if (!m_sample_rate) |
| 485 | m_sample_rate = 1000; |
| 486 | } |
| 487 | |
| 488 | |
| 450 | 489 | // recompute the timing parameters |
| 451 | 490 | attoseconds_t update_attoseconds = m_device.machine().sound().update_attoseconds(); |
| 452 | 491 | m_attoseconds_per_sample = ATTOSECONDS_PER_SECOND / m_sample_rate; |
| r29469 | r29470 | |
| 483 | 522 | assert(input.m_latency_attoseconds < update_attoseconds); |
| 484 | 523 | } |
| 485 | 524 | } |
| 525 | |
| 526 | // If synchronous, prime the timer |
| 527 | if (m_synchronous) |
| 528 | { |
| 529 | attotime time = m_device.machine().time(); |
| 530 | attoseconds_t next_edge = m_attoseconds_per_sample - (time.attoseconds % m_attoseconds_per_sample); |
| 531 | m_sync_timer->adjust(attotime(0, next_edge)); |
| 532 | } |
| 486 | 533 | } |
| 487 | 534 | |
| 488 | 535 | |
trunk/src/emu/sound.h
| r29469 | r29470 | |
| 19 | 19 | |
| 20 | 20 | |
| 21 | 21 | //************************************************************************** |
| 22 | // CONSTANTS |
| 23 | //************************************************************************** |
| 24 | |
| 25 | const int STREAM_SYNC = -1; // special rate value indicating a one-sample-at-a-time stream |
| 26 | // with actual rate defined by its input |
| 27 | |
| 28 | //************************************************************************** |
| 22 | 29 | // MACROS |
| 23 | 30 | //************************************************************************** |
| 24 | 31 | |
| r29469 | r29470 | |
| 133 | 140 | void postload(); |
| 134 | 141 | void generate_samples(int samples); |
| 135 | 142 | stream_sample_t *generate_resampled_data(stream_input &input, UINT32 numsamples); |
| 143 | void sync_update(void *, INT32); |
| 136 | 144 | |
| 137 | 145 | // linking information |
| 138 | | device_t & m_device; // owning device |
| 139 | | sound_stream * m_next; // next stream in the chain |
| 146 | device_t & m_device; // owning device |
| 147 | sound_stream * m_next; // next stream in the chain |
| 140 | 148 | |
| 141 | 149 | // general information |
| 142 | | UINT32 m_sample_rate; // sample rate of this stream |
| 143 | | UINT32 m_new_sample_rate; // newly-set sample rate for the stream |
| 150 | UINT32 m_sample_rate; // sample rate of this stream |
| 151 | UINT32 m_new_sample_rate; // newly-set sample rate for the stream |
| 152 | bool m_synchronous; // synchronous stream that runs at the rate of its input |
| 144 | 153 | |
| 145 | 154 | // timing information |
| 146 | | attoseconds_t m_attoseconds_per_sample;// number of attoseconds per sample |
| 147 | | INT32 m_max_samples_per_update;// maximum samples per update |
| 155 | attoseconds_t m_attoseconds_per_sample; // number of attoseconds per sample |
| 156 | INT32 m_max_samples_per_update; // maximum samples per update |
| 157 | emu_timer * m_sync_timer; // update timer for synchronous streams |
| 148 | 158 | |
| 149 | 159 | // input information |
| 150 | | dynamic_array<stream_input> m_input; // list of streams we directly depend upon |
| 151 | | dynamic_array<stream_sample_t *> m_input_array; // array of inputs for passing to the callback |
| 160 | dynamic_array<stream_input> m_input; // list of streams we directly depend upon |
| 161 | dynamic_array<stream_sample_t *> m_input_array; // array of inputs for passing to the callback |
| 152 | 162 | |
| 153 | 163 | // resample buffer information |
| 154 | | UINT32 m_resample_bufalloc; // allocated size of each resample buffer |
| 164 | UINT32 m_resample_bufalloc; // allocated size of each resample buffer |
| 155 | 165 | |
| 156 | 166 | // output information |
| 157 | | dynamic_array<stream_output> m_output; // list of streams which directly depend upon us |
| 158 | | dynamic_array<stream_sample_t *> m_output_array; // array of outputs for passing to the callback |
| 167 | dynamic_array<stream_output> m_output; // list of streams which directly depend upon us |
| 168 | dynamic_array<stream_sample_t *> m_output_array; // array of outputs for passing to the callback |
| 159 | 169 | |
| 160 | 170 | // output buffer information |
| 161 | | UINT32 m_output_bufalloc; // allocated size of each output buffer |
| 162 | | INT32 m_output_sampindex; // current position within each output buffer |
| 163 | | INT32 m_output_update_sampindex;// position at time of last global update |
| 164 | | INT32 m_output_base_sampindex;// sample at base of buffer, relative to the current emulated second |
| 171 | UINT32 m_output_bufalloc; // allocated size of each output buffer |
| 172 | INT32 m_output_sampindex; // current position within each output buffer |
| 173 | INT32 m_output_update_sampindex; // position at time of last global update |
| 174 | INT32 m_output_base_sampindex; // sample at base of buffer, relative to the current emulated second |
| 165 | 175 | |
| 166 | 176 | // callback information |
| 167 | | stream_update_func m_callback; // callback function |
| 168 | | void * m_param; // callback function parameter |
| 177 | stream_update_func m_callback; // callback function |
| 178 | void * m_param; // callback function parameter |
| 169 | 179 | }; |
| 170 | 180 | |
| 171 | 181 | |
trunk/src/emu/diexec.c
| r29469 | r29470 | |
| 492 | 492 | m_profiler = profile_type(index + PROFILER_DEVICE_FIRST); |
| 493 | 493 | m_inttrigger = index + TRIGGER_INT; |
| 494 | 494 | |
| 495 | | // fill in the input states and IRQ callback information |
| 496 | | for (int line = 0; line < ARRAY_LENGTH(m_input); line++) |
| 497 | | m_input[line].start(this, line); |
| 498 | | |
| 499 | 495 | // allocate timers if we need them |
| 500 | 496 | if (m_timed_interrupt_period != attotime::zero) |
| 501 | 497 | m_timedint_timer = device().machine().scheduler().timer_alloc(FUNC(static_trigger_periodic_interrupt), (void *)this); |
| 502 | | |
| 503 | | // register for save states |
| 504 | | device().save_item(NAME(m_suspend)); |
| 505 | | device().save_item(NAME(m_nextsuspend)); |
| 506 | | device().save_item(NAME(m_eatcycles)); |
| 507 | | device().save_item(NAME(m_nexteatcycles)); |
| 508 | | device().save_item(NAME(m_trigger)); |
| 509 | | device().save_item(NAME(m_totalcycles)); |
| 510 | | device().save_item(NAME(m_localtime)); |
| 511 | 498 | } |
| 512 | 499 | |
| 513 | 500 | |
| r29469 | r29470 | |
| 520 | 507 | { |
| 521 | 508 | // make sure somebody set us up the icount |
| 522 | 509 | assert_always(m_icountptr != NULL, "m_icountptr never initialized!"); |
| 510 | |
| 511 | // register for save states |
| 512 | device().save_item(NAME(m_suspend)); |
| 513 | device().save_item(NAME(m_nextsuspend)); |
| 514 | device().save_item(NAME(m_eatcycles)); |
| 515 | device().save_item(NAME(m_nexteatcycles)); |
| 516 | device().save_item(NAME(m_trigger)); |
| 517 | device().save_item(NAME(m_totalcycles)); |
| 518 | device().save_item(NAME(m_localtime)); |
| 519 | |
| 520 | // fill in the input states and IRQ callback information |
| 521 | for (int line = 0; line < ARRAY_LENGTH(m_input); line++) |
| 522 | m_input[line].start(this, line); |
| 523 | 523 | } |
| 524 | 524 | |
| 525 | 525 | |
trunk/src/emu/cpu/tms57002/tms57002.c
| r29469 | r29470 | |
| 22 | 22 | |
| 23 | 23 | tms57002_device::tms57002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 24 | 24 | : cpu_device(mconfig, TMS57002, "TMS57002", tag, owner, clock, "tms57002", __FILE__), |
| 25 | | program_config("program", ENDIANNESS_LITTLE, 32, 8, -2, ADDRESS_MAP_NAME(internal_pgm)), |
| 26 | | data_config("data", ENDIANNESS_LITTLE, 8, 20) |
| 25 | device_sound_interface(mconfig, *this), |
| 26 | program_config("program", ENDIANNESS_LITTLE, 32, 8, -2, ADDRESS_MAP_NAME(internal_pgm)), |
| 27 | data_config("data", ENDIANNESS_LITTLE, 8, 20) |
| 27 | 28 | { |
| 28 | 29 | } |
| 29 | 30 | |
| r29469 | r29470 | |
| 211 | 212 | if(st0 & ST0_WORD) { |
| 212 | 213 | if(st0 & ST0_SEL) { |
| 213 | 214 | int off = 16 - ((adr & 3) << 3); |
| 214 | | xrd = (xrd & ~(0xff << off)) | (v << off); |
| 215 | txrd = (txrd & ~(0xff << off)) | (v << off); |
| 215 | 216 | done = off == 0; |
| 216 | 217 | } else { |
| 217 | 218 | int off = 20 - ((adr & 7) << 2); |
| 218 | | xrd = (xrd & ~(0xf << off)) | ((v & 0xf) << off); |
| 219 | txrd = (txrd & ~(0xf << off)) | ((v & 0xf) << off); |
| 219 | 220 | done = off == 0; |
| 220 | 221 | } |
| 221 | 222 | } else { |
| 222 | 223 | if(st0 & ST0_SEL) { |
| 223 | 224 | int off = 16 - ((adr & 1) << 3); |
| 224 | | xrd = (xrd & ~(0xff << off)) | (v << off); |
| 225 | txrd = (txrd & ~(0xff << off)) | (v << off); |
| 225 | 226 | done = off == 8; |
| 226 | 227 | if(done) |
| 227 | | xrd &= 0xffff00; |
| 228 | txrd &= 0xffff00; |
| 228 | 229 | } else { |
| 229 | 230 | int off = 20 - ((adr & 3) << 2); |
| 230 | | xrd = (xrd & ~(0xf << off)) | ((v & 0xf) << off); |
| 231 | txrd = (txrd & ~(0xf << off)) | ((v & 0xf) << off); |
| 231 | 232 | done = off == 8; |
| 232 | 233 | if(done) |
| 233 | | xrd &= 0xffff00; |
| 234 | txrd &= 0xffff00; |
| 234 | 235 | } |
| 235 | 236 | } |
| 236 | 237 | if(done) { |
| 238 | xrd = txrd; |
| 237 | 239 | sti &= ~S_READ; |
| 238 | 240 | xm_adr = 0; |
| 239 | 241 | } else |
| r29469 | r29470 | |
| 782 | 784 | icount = 0; |
| 783 | 785 | } |
| 784 | 786 | |
| 787 | void tms57002_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 788 | { |
| 789 | assert(samples == 1); |
| 790 | |
| 791 | if(st0 & ST0_SIM) { |
| 792 | si[0] = (inputs[0][0] << 8) & 0xffffff; |
| 793 | si[1] = (inputs[1][0] << 8) & 0xffffff; |
| 794 | si[2] = (inputs[2][0] << 8) & 0xffffff; |
| 795 | si[3] = (inputs[3][0] << 8) & 0xffffff; |
| 796 | } else { |
| 797 | si[0] = inputs[0][0] & 0xffffff; |
| 798 | si[1] = inputs[1][0] & 0xffffff; |
| 799 | si[2] = inputs[2][0] & 0xffffff; |
| 800 | si[3] = inputs[3][0] & 0xffffff; |
| 801 | } |
| 802 | outputs[0][0] = INT16(so[0] >> 8); |
| 803 | outputs[1][0] = INT16(so[1] >> 8); |
| 804 | outputs[2][0] = INT16(so[2] >> 8); |
| 805 | outputs[3][0] = INT16(so[3] >> 8); |
| 806 | |
| 807 | sync_w(1); |
| 808 | } |
| 809 | |
| 785 | 810 | void tms57002_device::device_start() |
| 786 | 811 | { |
| 787 | 812 | sti = S_IDLE; |
| r29469 | r29470 | |
| 812 | 837 | |
| 813 | 838 | m_icountptr = &icount; |
| 814 | 839 | |
| 840 | stream_alloc(4, 4, STREAM_SYNC); |
| 841 | |
| 815 | 842 | save_item(NAME(macc)); |
| 816 | 843 | |
| 817 | 844 | save_item(NAME(cmem)); |
| r29469 | r29470 | |
| 829 | 856 | save_item(NAME(xba)); |
| 830 | 857 | save_item(NAME(xwr)); |
| 831 | 858 | save_item(NAME(xrd)); |
| 859 | save_item(NAME(txrd)); |
| 832 | 860 | save_item(NAME(creg)); |
| 833 | 861 | |
| 834 | 862 | save_item(NAME(pc)); |
trunk/src/emu/cpu/tms57002/tms57002.h
| r29469 | r29470 | |
| 12 | 12 | #ifndef __TMS57002_H__ |
| 13 | 13 | #define __TMS57002_H__ |
| 14 | 14 | |
| 15 | | class tms57002_device : public cpu_device { |
| 15 | class tms57002_device : public cpu_device, public device_sound_interface { |
| 16 | 16 | public: |
| 17 | 17 | tms57002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 18 | 18 | |
| r29469 | r29470 | |
| 29 | 29 | protected: |
| 30 | 30 | virtual void device_start(); |
| 31 | 31 | virtual void device_reset(); |
| 32 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 32 | 33 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const; |
| 33 | 34 | virtual UINT32 execute_min_cycles() const; |
| 34 | 35 | virtual UINT32 execute_max_cycles() const; |
| r29469 | r29470 | |
| 126 | 127 | UINT32 si[4], so[4]; |
| 127 | 128 | |
| 128 | 129 | UINT32 st0, st1, sti; |
| 129 | | UINT32 aacc, xoa, xba, xwr, xrd, creg; |
| 130 | UINT32 aacc, xoa, xba, xwr, xrd, txrd, creg; |
| 130 | 131 | |
| 131 | 132 | UINT8 pc, hpc, ca, id, ba0, ba1, rptc, rptc_next, sa; |
| 132 | 133 | |