2 Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
5 [ADPCM RF6C68 with RAM]
8 #include "../../common.h"
10 #include "../debugger.h"
12 #define EVENT_DAC_SAMPLE 1
14 void RF5C68::initialize()
17 memset(wave_memory, 0x00, sizeof(wave_memory));
22 for(int i = 0; i < 8; i++) {
23 dac_addr_st[i].d = 0x00;
24 dac_env[i] = 0x0000080;
25 dac_pan[(i << 1) + 0] = 0x000000f;
26 dac_pan[(i << 1) + 1] = 0x000000f;
30 dac_addr[i] = 0x00000000;
31 dac_force_load[i] = false;
38 if(d_debugger != NULL) {
39 d_debugger->set_device_name(_T("Debugger (RICOH RF5C68)"));
40 d_debugger->set_context_mem(this);
41 d_debugger->set_context_io(vm->dummy);
45 void RF5C68::release()
47 if(sample_buffer != NULL) free(sample_buffer);
53 is_mute = true; // OK?
54 for(int i = 0; i < 8; i++) {
55 dac_addr_st[i].d = 0x00;
56 dac_env[i] = 0x0000080;
57 dac_pan[(i << 1) + 0] = 0x0000008;
58 dac_pan[(i << 1) + 1] = 0x0000008;
62 dac_addr[i] = 0x00000000;
63 dac_force_load[i] = false;
65 for(int i = 0; i < 16; i++) {
66 dac_tmpval[i] = 0x00000000;
68 if((sample_buffer != NULL) && (sample_length > 0)) {
69 memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
71 if(event_dac_sample != -1) {
72 cancel_event(this, event_dac_sample);
73 event_dac_sample = -1;
76 sample_tick_us = 1.0e6 / ((double)mix_rate);
77 register_event(this, EVENT_DAC_SAMPLE, sample_tick_us, true, &event_dac_sample);
84 uint32_t RF5C68::read_signal(int ch)
86 if(ch >= SIG_RF5C68_REG_ADDR_ST) {
87 if(ch >= 0x100) return 0x00;
88 int major_num = ch & 0xf8;
89 int local_ch = ch & 0x07;
91 case SIG_RF5C68_REG_ADDR_ST:
92 return dac_addr_st[local_ch].d;
94 case SIG_RF5C68_REG_ADDR:
95 return dac_addr[local_ch];
97 case SIG_RF5C68_REG_ENV:
98 return dac_env[local_ch];
100 case SIG_RF5C68_REG_LPAN:
101 return dac_pan[(local_ch << 1) + 0];
103 case SIG_RF5C68_REG_RPAN:
104 return dac_pan[(local_ch << 1) + 1];
106 case SIG_RF5C68_REG_LS:
107 return dac_ls[local_ch].d;
109 case SIG_RF5C68_REG_FD:
110 return dac_fd[local_ch].d;
112 case SIG_RF5C68_FORCE_LOAD:
113 return ((dac_force_load[local_ch]) ? 0xffffffff : 0x00000000);
120 case SIG_RF5C68_MUTE:
121 return ((is_mute) ? 0xffffffff : 0x00000000);
123 case SIG_RF5C68_REG_ON:
124 return ((dac_on) ? 0xffffffff : 0x00000000);
126 case SIG_RF5C68_REG_BANK:
129 case SIG_RF5C68_REG_CH:
139 void RF5C68::write_signal(int ch, uint32_t data, uint32_t mask)
143 case SIG_RF5C68_DAC_PERIOD:
145 __DECL_ALIGNED(16) uint8_t tmpval[8] = {0};
146 __DECL_VECTORIZED_LOOP
147 for(int i = 0; i < 16; i++) {
150 for(int ch = 0; ch < 8; ch++) {
152 uint32_t addr_old = (dac_addr[ch] & 0x7fffffff) >> 11;
154 if((addr_old & 0x0fff) == 0x0fff) {
155 // Will beyond of boundary
156 write_signals(&interrupt_boundary, ((addr_old & 0xe000) >> 13) | 0x00000008);
157 // out_debug_log(_T("PCM INTERRUPT CH=%d ADDR=%04X"), ch, addr_old & 0xffff);
161 tmpval[ch] = wave_memory[addr_old & 0xffff];
162 if(tmpval[ch] == 0xff) {
164 dac_addr[ch] = (uint32_t)(dac_ls[ch].w.l) << 11;
165 addr_old = dac_addr[ch] >> 11;
166 tmpval[ch] = wave_memory[addr_old & 0xffff];
167 if(tmpval[ch] == 0xff) {
169 // dac_onoff[ch] = false; // STOP
170 continue; // This channel will stop
173 dac_addr[ch] += dac_fd[ch].d;
174 dac_addr[ch] = dac_addr[ch] & 0x7fffffff;
177 __DECL_ALIGNED(16) bool sign[16] = {false};
178 __DECL_ALIGNED(16) int32_t val[16] = {0};
179 __DECL_VECTORIZED_LOOP
180 for(int ch = 0; ch < 8; ch++) {
182 sign[chd + 0] = (dac_onoff[ch]) ? ((tmpval[ch] & 0x80) == 0) : false; // 0 = minus
183 sign[chd + 1] = sign[chd + 0];
184 val[chd + 0] = (dac_onoff[ch]) ? (tmpval[ch] & 0x7f) : 0;
185 val[chd + 1] = val[chd + 0];
187 // VAL = VAL * ENV * PAN
188 __DECL_VECTORIZED_LOOP
189 for(int chd = 0; chd < 16; chd++) {
190 val[chd] = val[chd] * dac_env[chd >> 1];
191 val[chd] = val[chd] * dac_pan[chd];
194 __DECL_VECTORIZED_LOOP
195 for(int chd = 0; chd < 16; chd++) {
196 dac_tmpval[chd] = (sign[chd]) ? -val[chd] : val[chd];
198 // Re-Init sample buffer
199 __DECL_VECTORIZED_LOOP
200 for(int i = 0; i < 2; i++) {
201 sample_buffer[i] = 0;
204 __DECL_VECTORIZED_LOOP
205 for(int chd = 0; chd < 16; chd++) {
206 sample_buffer[chd & 1] += dac_tmpval[chd];
208 __DECL_ALIGNED(16) static const int32_t uplimit[16] = {(127 << 6)};
209 __DECL_ALIGNED(16) static const int32_t lowlimit[16] = {(-127 << 6)};
211 __DECL_VECTORIZED_LOOP
212 for(int chd = 0; chd < 16; chd++) {
213 dac_tmpval[chd] = (dac_tmpval[chd] > uplimit[chd]) ? uplimit[chd] : ((dac_tmpval[chd] < lowlimit[chd]) ? lowlimit[chd] : dac_tmpval[chd]);
217 case SIG_RF5C68_CLEAR_INTR:
218 write_signals(&interrupt_boundary, 0x80000000);
220 case SIG_RF5C68_SET_ALL_INTR:
221 write_signals(&interrupt_boundary, 0x80000008);
223 case SIG_RF5C68_MUTE:
224 is_mute = ((data & mask) != 0) ? true : false;
231 void RF5C68::write_io8(uint32_t addr, uint32_t data)
233 uint32_t naddr = addr & 0x0f;
236 dac_env[dac_ch] = data & 0xff;
237 // out_debug_log(_T("DAC REG 00 (ENV) CH=%d RAW=%02X"),
241 dac_pan[(dac_ch << 1) + 0] = data & 0x0f;
242 dac_pan[(dac_ch << 1) + 1] = (data & 0xf0) >> 4;
243 // out_debug_log(_T("DAC REG 01 (PAN) CH=%d L=%01X R=%01X"),
244 // dac_ch, data & 0x0f, (data & 0xf0) >> 4);
247 dac_fd[dac_ch].b.l = data & 0xff;
248 // out_debug_log(_T("DAC REG 02 (FD LOW) CH=%d RAW=%02X"),
252 dac_fd[dac_ch].b.h = data & 0xff;
253 // out_debug_log(_T("DAC REG 03 (FD HIGH) CH=%d RAW=%02X"),
257 dac_ls[dac_ch].b.l = data & 0xff;
258 // out_debug_log(_T("DAC REG 04 (LS) CH=%d RAW=%02X"),
262 dac_ls[dac_ch].b.h = data & 0xff;
263 // out_debug_log(_T("DAC REG 05 (ADDR STEP HIGH) CH=%d RAW=%02X"),
267 dac_addr_st[dac_ch].d = 0;
268 dac_addr_st[dac_ch].b.h = data & 0xff;
269 dac_addr[dac_ch] = (uint32_t)(dac_addr_st[dac_ch].w.l) << 11;
270 // out_debug_log(_T("DAC REG 06 (ADDR STEP HIGH) CH=%d RAW=%02X"),
273 case 0x07: // Control
274 dac_on = ((data & 0x80) != 0) ? true : false;
275 if((data & 0x40) != 0) { // CB2-0
276 dac_ch = data & 0x07;
278 dac_bank = ((data & 0x0f) << 12);
280 // out_debug_log(_T("DAC REG 07 RAW=%02X ON=%s CH=%d BANK=%04X"),
282 // (dac_on) ? _T("ON ") :_T("OFF"),
283 // dac_ch, dac_bank);
285 case 0x08: // ON/OFF per CH
287 uint32_t mask = 0x01;
288 for(int i = 0; i < 8; i++) {
289 bool onoff = dac_onoff[i];
290 if((mask & data) == 0) {
293 dac_onoff[i] = false;
295 // if(!(onoff) && (dac_onoff[i])) { // Force reload
296 // dac_addr[ch] = (uint32_t)(dac_addr_st[ch].w.l) << 11;
301 // out_debug_log(_T("DAC REG 08 (DAC/ONOFF) RAW=%02X"),
309 uint32_t RF5C68::read_io8(uint32_t addr)
315 uint32_t RF5C68::read_memory_mapped_io8(uint32_t addr)
317 addr = (addr & 0xfff) | dac_bank;
318 if(d_debugger != NULL && d_debugger->now_device_debugging) {
319 return d_debugger->read_via_debugger_data8(addr);
324 return read_via_debugger_data8(addr);
329 uint32_t RF5C68::read_memory_mapped_io16(uint32_t addr)
331 addr = (addr & 0xfff) | dac_bank;
332 if(d_debugger != NULL && d_debugger->now_device_debugging) {
333 return d_debugger->read_via_debugger_data16(addr);
338 return read_via_debugger_data16(addr);
343 void RF5C68::write_memory_mapped_io8(uint32_t addr, uint32_t data)
345 addr = (addr & 0xfff) | dac_bank;
346 // if(dac_on) don't write <- Is correct?
347 if(d_debugger != NULL && d_debugger->now_device_debugging) {
348 d_debugger->write_via_debugger_data8(addr, data);
351 write_via_debugger_data8(addr, data);
357 void RF5C68::write_memory_mapped_io16(uint32_t addr, uint32_t data)
359 addr = (addr & 0xfff) | dac_bank;
360 if(d_debugger != NULL && d_debugger->now_device_debugging) {
361 d_debugger->write_via_debugger_data16(addr, data);
364 write_via_debugger_data16(addr, data);
370 void RF5C68::set_volume(int ch, int decibel_l, int decibel_r)
372 volume_l = decibel_to_volume(decibel_l);
373 volume_r = decibel_to_volume(decibel_r);
376 void RF5C68::event_callback(int id, int err)
378 if(id == EVENT_DAC_SAMPLE) {
379 __DECL_ALIGNED(16) int32_t val[2] = {0}; // l,r
380 if(sample_count < sample_length) {
382 for(int ch = 0; ch < 16; ch++) {
383 val[ch & 1] += (dac_onoff[ch >> 1]) ? dac_tmpval[ch] : 0;
386 int32_t* p = &(sample_buffer[sample_count << 1]);
387 for(int i = 0; i < 2; i++) {
395 void RF5C68::mix(int32_t* buffer, int cnt)
399 // ToDo: supress pop noise.
403 if(sample_buffer != NULL) {
404 for(int i = 0; i < (cnt << 1); i += 2) {
405 // ToDo: interpoolate.
406 buffer[i] += (apply_volume(sample_buffer[0], volume_l) >> 2);
407 buffer[i + 1] += (apply_volume(sample_buffer[1], volume_r) >> 2);
412 void RF5C68::initialize_sound(int sample_rate, int samples)
414 if((sample_rate > 0) && (samples > 0)) {
415 mix_rate = sample_rate;
416 sample_length = samples;
417 if(sample_buffer != NULL) {
420 sample_buffer = (int32_t*)malloc(sample_length * sizeof(int32_t) * 2);
421 if(sample_buffer != NULL) {
422 memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
424 if(event_dac_sample != -1) {
425 cancel_event(this, event_dac_sample);
426 event_dac_sample = -1;
429 // TOWNS::ADPCM::event_callback() -> SIG_RF5C68_DAC_PERIOD(=DRIVE CLOCK from VM)
430 // -> RF5C68::event_callback()(=AUDIO MIXING CLOCK by EMU)
431 // -> RF5C68::mix() -> OSD::SOUND
432 sample_tick_us = 1.0e6 / ((double)mix_rate);
433 // register_event(this, EVENT_DAC_SAMPLE, sample_tick_us, true, &event_dac_sample);
436 if(sample_buffer != NULL) {
439 sample_buffer = NULL;
442 if(event_dac_sample != -1) {
443 cancel_event(this, event_dac_sample);
444 event_dac_sample = -1;
446 sample_tick_us = 0.0;
451 void RF5C68::write_debug_data8(uint32_t addr, uint32_t data)
453 wave_memory[addr & 0xffff] = data;
456 uint32_t RF5C68::read_debug_data8(uint32_t addr)
458 return wave_memory[addr & 0xffff];
461 void RF5C68::write_via_debugger_data8(uint32_t addr, uint32_t data)
463 wave_memory[addr] = data;
466 void RF5C68::write_via_debugger_data16(uint32_t addr, uint32_t data)
470 wave_memory[addr + 0] = _b.b.l;
471 wave_memory[(addr + 1) & 0xffff] = _b.b.h;
475 uint32_t RF5C68::read_via_debugger_data8(uint32_t addr)
477 return wave_memory[addr];
480 uint32_t RF5C68::read_via_debugger_data16(uint32_t addr)
483 _b.b.l = wave_memory[addr + 0];
484 _b.b.h = wave_memory[(addr + 1) & 0xffff];
488 bool RF5C68::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
490 _TCHAR sbuf[8][512] = {0};
491 _TCHAR sbuf2[4096] = {0};
492 for(int i = 0; i < 8; i++) {
493 my_stprintf_s(sbuf[i], sizeof(sbuf[i]),
494 _T("CH%d: %s: ENV=%02X LPAN=%02X RPAN=%02X FD=%04X LS=%04X ADDR=%08X ADDR_ST=%08X\n")
495 , i, (dac_onoff[i]) ? _T("ON ") : _T("OFF")
496 , dac_env[i], dac_pan[(i << 1) + 0], dac_pan[(i << 1) + 1]
497 , dac_fd[i].w.l, dac_ls[i].w.l
498 , dac_addr[i], dac_addr_st[i].w.l
501 for(int i = 0; i < 8; i++) {
502 my_tcscat_s(sbuf2, sizeof(sbuf2), sbuf[i]);
504 my_stprintf_s(buffer, buffer_len,
505 _T("DAC %s BANK=%01X CH=%d MUTE=%s\n")
507 , (dac_on) ? _T("ON ") : _T("OFF"), dac_bank, dac_ch, (is_mute) ? _T("ON ") : _T("OFF")
512 #define STATE_VERSION 1
514 bool RF5C68::process_state(FILEIO* state_fio, bool loading)
516 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
519 if(!state_fio->StateCheckInt32(this_device_id)) {
522 state_fio->StateValue(dac_on);
523 state_fio->StateValue(dac_bank);
524 state_fio->StateValue(dac_ch);
525 state_fio->StateValue(is_mute);
526 state_fio->StateArray(dac_onoff, sizeof(dac_onoff), 1);
527 state_fio->StateArray(dac_addr_st, sizeof(dac_addr_st), 1);
528 state_fio->StateArray(dac_addr, sizeof(dac_addr), 1);
529 state_fio->StateArray(dac_env, sizeof(dac_env), 1);
530 state_fio->StateArray(dac_pan, sizeof(dac_pan), 1);
531 state_fio->StateArray(dac_ls, sizeof(dac_ls), 1);
532 state_fio->StateArray(dac_fd, sizeof(dac_fd), 1);
533 state_fio->StateArray(dac_force_load, sizeof(dac_force_load), 1);
534 state_fio->StateArray(dac_tmpval, sizeof(dac_tmpval), 1);
536 state_fio->StateArray(wave_memory, sizeof(wave_memory), 1);
537 state_fio->StateValue(event_dac_sample);
541 if(event_dac_sample != -1) {
542 cancel_event(this, event_dac_sample);
543 event_dac_sample = -1;
546 sample_tick_us = 1.0e6 / ((double)mix_rate);
547 register_event(this, EVENT_DAC_SAMPLE, sample_tick_us, true, &event_dac_sample);