OSDN Git Service

[VM][RF5C68][FMTOWNS][ADPCM] RF5C68: Driven by internal event.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Mon, 27 Nov 2023 14:04:38 +0000 (23:04 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Mon, 27 Nov 2023 14:04:38 +0000 (23:04 +0900)
- [RF5C68] If you want to drive by external signal (SIG_RF5C68_DAC_PERIOD) ,
  Put "#define RF5C68_DRIVEN_BY_EXTERNAL_CLOCK 1" to VM's header.
- [RF5C68] PCM period: Enhance env registers to be faster.
- [RF5C68] PCM period: Make sing variables to int32_t to be faster.
- [RF5C68] Make [read|write]_memory_mapped_io8() to [read|write]_memory_mapped_io8w().
- [RF5C68] Remove 16bit bus width memory acccessing.Maybe this is not
           needed.
- [RF5C68] Make memoryaccess faster a bit :-)
- [RF5C68][WIP] Make mix() to be more correctness.

- [FMTONWS][ADPCM] Remove read/write PCM memory , this is
  owned by RF5C68.

source/src/vm/fmtowns/adpcm.cpp
source/src/vm/fmtowns/adpcm.h
source/src/vm/fmtowns/fmtowns.cpp
source/src/vm/fmtowns/rf5c68.cpp
source/src/vm/fmtowns/rf5c68.h

index dc38822..4aed207 100644 (file)
 namespace FMTOWNS {
 
 #define EVENT_ADC_CLOCK   1
-#define EVENT_ADPCM_CLOCK 2
 
 void ADPCM::initialize()
 {
        adc_fifo = new FIFO(64); // OK?
        event_adc_clock = -1;
-       event_adpcm_clock = -1;
 }
 
 void ADPCM::release()
@@ -48,11 +46,6 @@ void ADPCM::reset()
        write_signals(&outputs_allmute, 0xffffffff); // OK?
 
        initialize_adc_clock(-1);
-       if(event_adpcm_clock >= 0) {
-               cancel_event(this, event_adpcm_clock);
-       }
-       // Tick is (8.0e6 / 384.0)[Hz] .. Is this true?
-       register_event(this, EVENT_ADPCM_CLOCK, (384.0 * 2.0) / 16.0, true, &event_adpcm_clock);
 }
 
 void ADPCM::initialize_adc_clock(int freq)
@@ -79,9 +72,6 @@ void ADPCM::event_callback(int id, int err)
                        d_adc->read_data8(SIG_AD7820_DATA_REG); // Dummy read, start to  sample.
                }
                break;
-       case EVENT_ADPCM_CLOCK:
-               d_rf5c68->write_signal(SIG_RF5C68_DAC_PERIOD, 1, 1);
-               break;
        }
 }
 
@@ -91,7 +81,6 @@ uint32_t ADPCM::read_io8(uint32_t addr)
          0x04d5 : OPN2/ADPCM MUTE
          0x04e7 - 0x04e8 : ADC
          0x04e9 - 0x04ec : DAC CONTROL
-         0x04f0 - 0x04f8 : DAC
        */
        uint8_t val = 0x00;
        switch(addr) {
@@ -129,7 +118,6 @@ uint32_t ADPCM::read_io8(uint32_t addr)
                }
                break;
        default:
-               if((addr & 0xff) >= 0xf0) val = d_rf5c68->read_io8(addr & 0x0f); // AROUND DAC
                break;
        }
        return val;
@@ -141,7 +129,6 @@ void ADPCM::write_io8(uint32_t addr, uint32_t data)
          0x04d5 : OPN2/ADPCM MUTE
          0x04e7 - 0x04e8 : ADC
          0x04e9 - 0x04ec : DAC CONTROL
-         0x04f0 - 0x04f8 : DAC
        */
        switch(addr) {
        case 0x04d5:
@@ -161,66 +148,10 @@ void ADPCM::write_io8(uint32_t addr, uint32_t data)
                write_signals(&outputs_allmute, ((data & 0x40) == 0) ? 0xffffffff : 0x00000000);
                break;
        default:
-               if(addr >= 0x04f0) {
-                       d_rf5c68->write_io8(addr & 0x0f, data);
-               }
                break;
        }
 }
 
-uint32_t ADPCM::read_memory_mapped_io8w(uint32_t addr, int *wait)
-{
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       return d_rf5c68->read_memory_mapped_io8(addr & 0x7fff);
-}
-
-uint32_t ADPCM::read_memory_mapped_io16w(uint32_t addr, int *wait)
-{
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       return d_rf5c68->read_memory_mapped_io16(addr & 0x7fff);
-}
-
-void ADPCM::write_memory_mapped_io8w(uint32_t addr, uint32_t data, int* wait)
-{
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       d_rf5c68->write_memory_mapped_io8(addr & 0x7fff, data);
-}
-
-void ADPCM::write_memory_mapped_io16w(uint32_t addr, uint32_t data, int* wait)
-{
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       d_rf5c68->write_memory_mapped_io16(addr & 0x7fff, data);
-}
-
-
-uint32_t ADPCM::read_dma_data8w(uint32_t addr, int* wait)
-{
-       return d_rf5c68->read_dma_data8w(addr & 0x7fff, wait);
-}
-
-uint32_t ADPCM::read_dma_data16w(uint32_t addr, int* wait)
-{
-       return d_rf5c68->read_dma_data16w(addr & 0x7fff, wait);
-}
-
-void ADPCM::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
-{
-       d_rf5c68->write_dma_data8w(addr & 0x7fff, data, wait);
-}
-
-void ADPCM::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
-{
-       d_rf5c68->write_dma_data16w(addr & 0x7fff, data, wait);
-}
-
 void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
 {
        if(ch == SIG_ADPCM_WRITE_INTERRUPT) {
@@ -277,7 +208,8 @@ uint32_t ADPCM::read_signal(int ch)
 {
        return 0;
 }
-#define STATE_VERSION  1
+
+#define STATE_VERSION  2
 
 bool ADPCM::process_state(FILEIO* state_fio, bool loading)
 {
@@ -299,7 +231,6 @@ bool ADPCM::process_state(FILEIO* state_fio, bool loading)
        state_fio->StateValue(latest_dac_intr);
 
        state_fio->StateValue(event_adc_clock);
-       state_fio->StateValue(event_adpcm_clock);
        return true;
 }
 
index d9f6b4b..8ae3b8f 100644 (file)
@@ -75,16 +75,6 @@ public:
        uint32_t __FASTCALL read_io8(uint32_t addr) override;
        void     __FASTCALL write_io8(uint32_t addr, uint32_t data) override;
 
-       uint32_t __FASTCALL read_dma_data8w(uint32_t addr, int* wait) override;
-       uint32_t __FASTCALL read_dma_data16w(uint32_t addr, int* wait) override;
-       void     __FASTCALL write_dma_data8w(uint32_t addr, uint32_t data, int* wait) override;
-       void     __FASTCALL write_dma_data16w(uint32_t addr, uint32_t data, int* wait) override;
-
-       uint32_t __FASTCALL read_memory_mapped_io8w(uint32_t addr, int* wait) override;
-       uint32_t __FASTCALL read_memory_mapped_io16w(uint32_t addr, int* wait) override;
-       void     __FASTCALL write_memory_mapped_io8w(uint32_t addr, uint32_t data, int* wait) override;
-       void     __FASTCALL write_memory_mapped_io16w(uint32_t addr, uint32_t data, int* wait) override;
-
        void __FASTCALL write_signal(int ch, uint32_t data, uint32_t mask) override;
        uint32_t __FASTCALL read_signal(int ch) override;
 
index 30157a2..7eb2f9c 100644 (file)
@@ -429,7 +429,7 @@ VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu)
        memory->set_context_timer(timer);
        memory->set_context_serial_rom(serialrom);
        memory->set_context_sprite(sprite);
-       memory->set_context_pcm(adpcm);
+       memory->set_context_pcm(rf5c68);
        memory->set_context_iccard(iccard1, 0);
        memory->set_context_iccard(iccard2, 1);
 
@@ -665,7 +665,7 @@ VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu)
        io->set_iomap_single_rw(0x04ea, adpcm); // PCM INTERRUPT MASK
        io->set_iomap_single_r (0x04eb, adpcm); // PCM INTERRUPT STATUS
        io->set_iomap_single_w (0x04ec, adpcm); // PCM LED/MUTE
-       io->set_iomap_range_w (0x04f0, 0x04f8, adpcm); // PCM CONTROL REGS (WO?)
+       io->set_iomap_range_w (0x04f0, 0x04f8, rf5c68); // PCM CONTROL REGS (WO?)
 
        //io->set_iomap_single_rw(0x510, newpcm); // PCM BANK (after MX)
        //io->set_iomap_single_rw(0x511, newpcm); // PCM DMA STATUS(after MX)
index 6744dc1..6e893a7 100644 (file)
 #include "../debugger.h"
 #include "../../types/util_sound.h"
 
+#define EVENT_DAC_PERIOD       1
+#define EVENT_LPF_PERIOD       2
+
 void RF5C68::initialize()
 {
+       DEVICE::initialize();
+       _RF5C68_DRIVEN_BY_EXTERNAL_CLOCK = osd->check_feature(_T("RF5C68_DRIVEN_BY_EXTERNAL_CLOCK"));
+
+       memset(wave_memory, 0xff, sizeof(wave_memory));
        // DAC
-//     memset(wave_memory, 0xff, sizeof(wave_memory));
+       volume_l = volume_r = 1024;
+       is_mute = true;
+       mix_factor = 4096;
+       event_dac = -1;
+       event_lpf = -1;
+
        if(d_debugger != NULL) {
                d_debugger->set_device_name(_T("Debugger (RICOH RF5C68)"));
                d_debugger->set_context_mem(this);
@@ -23,17 +35,26 @@ void RF5C68::initialize()
 
 void RF5C68::release()
 {
+       //std::lock_guard<std::recursive_mutex> locker(m_locker);
        if(sample_buffer != NULL) free(sample_buffer);
        sample_buffer = NULL;
 }
 
 void RF5C68::reset()
 {
+       std::lock_guard<std::recursive_mutex> locker(m_locker);
+       if(event_dac >= 0) cancel_event(this, event_dac);
+       if(event_lpf >= 0) cancel_event(this, event_lpf);
+       event_dac = -1;
+       event_lpf = -1;
+       dac_on = false; // OK?
        is_mute = true; // OK?
+
        memset(wave_memory, 0xff, sizeof(wave_memory));
        for(int i = 0; i < 8; i++) {
                dac_addr_st[i].d = 0x00;
-               dac_env[i] = 0x00000ff;
+               dac_env[(i << 1) + 0] = 0x00000ff;
+               dac_env[(i << 1) + 1] = 0x00000ff;
                dac_pan[(i << 1) + 0] = 0x0000000;
                dac_pan[(i << 1) + 1] = 0x0000000;
                dac_ls[i].d = 0x0000;
@@ -45,21 +66,18 @@ void RF5C68::reset()
        for(int i = 0; i < 16; i++) {
                dac_tmpval[i] = 0x00000000;
        }
-       if((sample_buffer != NULL) && (sample_length > 0)) {
-               memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
+       if((sample_buffer != NULL) && (sample_length.load() > 0)) {
+               memset(sample_buffer, 0x00, sample_length.load() * sizeof(int32_t) * 2);
        }
        read_pointer = 0;
        sample_pointer = 0;
        sample_words = 0;
+       lastsample_l = apply_volume(0, volume_l) >> 1;
+       lastsample_r = apply_volume(0, volume_r) >> 1;
 
-       if(mix_rate > 0) {
-               sample_tick_us = 1.0e6 / ((double)mix_rate);
-       } else {
-               sample_tick_us = 0;
-       }
-       mix_factor = (int)(dac_rate * 4096.0 / (double)mix_rate);
+       //mix_factor = set_mix_factor(dac_rate, mix_rate);
        mix_count = 0;
-       dac_on = false;
+
 }
 
 uint32_t RF5C68::read_signal(int ch)
@@ -76,7 +94,7 @@ uint32_t RF5C68::read_signal(int ch)
                        return dac_addr[local_ch];
                        break;
                case SIG_RF5C68_REG_ENV:
-                       return dac_env[local_ch];
+                       return dac_env[(local_ch << 1) + 0];
                        break;
                case SIG_RF5C68_REG_LPAN:
                        return dac_pan[(local_ch << 1) + 0];
@@ -117,101 +135,114 @@ uint32_t RF5C68::read_signal(int ch)
        return 0x00;
 }
 
-void RF5C68::write_signal(int ch, uint32_t data, uint32_t mask)
+void RF5C68::do_dac_period()
 {
-       switch(ch)
-       {
-       case SIG_RF5C68_DAC_PERIOD:
-               if(dac_on) {
+       if(dac_on) {
                __DECL_ALIGNED(16) uint8_t tmpval[8] = {0};
-__DECL_VECTORIZED_LOOP
-                       for(int i = 0; i < 16; i++) {
-                               dac_tmpval[i] = 0;
-                       }
-                       for(int ch = 0; ch < 8; ch++) {
-                               if(dac_onoff[ch]) {
-                                       uint32_t addr_old = (dac_addr[ch] >> 11) & 0xffff;
-                                       uint32_t addr_new;
-                                       if((addr_old & 0x0fff) == 0x0fff) {
-                                               // Will beyond of boundary
-                                               write_signals(&interrupt_boundary, ((addr_old & 0xe000) >> 13) | 0x00000008);
+               __DECL_VECTORIZED_LOOP
+               for(int i = 0; i < 16; i++) {
+                       dac_tmpval[i] = 0;
+               }
+               for(int ch = 0; ch < 8; ch++) {
+                       if(dac_onoff[ch]) {
+                               uint32_t addr_old = (dac_addr[ch] >> 11) & 0xffff;
+                               uint32_t addr_new;
+                               if((addr_old & 0x0fff) == 0x0fff) {
+                                       // Will beyond of boundary
+                                       write_signals(&interrupt_boundary, ((addr_old & 0xe000) >> 13) | 0x00000008);
 //                                             out_debug_log(_T("PCM INTERRUPT CH=%d ADDR=%04X"), ch, addr_old & 0xffff);
-                                       }
+                               }
 
-                                       int chd = ch << 1;
+                               int chd = ch << 1;
+                               tmpval[ch] = wave_memory[addr_old & 0xffff];
+                               if(tmpval[ch] == 0xff) {
+                                       // Loop
+                                       dac_addr[ch] = ((uint32_t)(dac_ls[ch].w.l)) << 11;
+                                       addr_old = ((uint32_t)(dac_ls[ch].w.l));
                                        tmpval[ch] = wave_memory[addr_old & 0xffff];
                                        if(tmpval[ch] == 0xff) {
-                                               // Loop
-                                               dac_addr[ch] = ((uint32_t)(dac_ls[ch].w.l)) << 11;
-                                               addr_old = ((uint32_t)(dac_ls[ch].w.l));
-                                               tmpval[ch] = wave_memory[addr_old & 0xffff];
-                                               if(tmpval[ch] == 0xff) {
-                                                       tmpval[ch] = 0x00;
-                                                       dac_onoff[ch] = false; // STOP
-                                                       continue; // This channel will stop
-                                               }
+                                               tmpval[ch] = 0x00;
+                                               dac_onoff[ch] = false; // STOP
+                                               continue; // This channel will stop
                                        }
-                                       dac_addr[ch] += dac_fd[ch].d;
-//                                     dac_addr[ch] = dac_addr[ch] & ((1 << 28) - 1);
                                }
+                               dac_addr[ch] += dac_fd[ch].d;
+//                                     dac_addr[ch] = dac_addr[ch] & ((1 << 28) - 1);
                        }
-                       __DECL_ALIGNED(16) bool sign[16] = {false};
-                       __DECL_ALIGNED(16) int32_t val[16] = {0};
-__DECL_VECTORIZED_LOOP
-                       for(int ch = 0; ch < 8; ch++) {
-                               int chd = ch << 1;
-                               sign[chd + 0] = (dac_onoff[ch]) ? ((tmpval[ch] & 0x80) == 0) : false; // 0 = minus
-                               sign[chd + 1] = sign[chd + 0];
-                               val[chd + 0] = (dac_onoff[ch]) ? (tmpval[ch] & 0x7f) : 0;
-                               val[chd + 1] = val[chd + 0];
-                       }
-                       // VAL = VAL * ENV * PAN
-__DECL_VECTORIZED_LOOP
-                       for(int chd = 0; chd < 16; chd++) {
-                               val[chd] = val[chd] * dac_env[chd >> 1];
-                               val[chd] = val[chd] * dac_pan[chd];
+               }
+               __DECL_ALIGNED(16) int32_t sign[16] = {1};
+               __DECL_ALIGNED(16) int32_t val[16] = {0};
+               __DECL_VECTORIZED_LOOP
+               for(int ch = 0; ch < 8; ch++) {
+                       int chd = ch << 1;
+                       sign[chd + 0] = (dac_onoff[ch]) ? (((tmpval[ch] & 0x80) == 0) ? -1 : 1): 1; // 0 = minus
+                       sign[chd + 1] = sign[chd + 0];
+                       val[chd + 0] = (dac_onoff[ch]) ? (tmpval[ch] & 0x7f) : 0;
+                       val[chd + 1] = val[chd + 0];
+               }
+               // VAL = VAL * ENV * PAN
+               __DECL_VECTORIZED_LOOP
+               for(int chd = 0; chd < 16; chd++) {
+                       val[chd] = val[chd] * dac_env[chd];
+               }
+               __DECL_VECTORIZED_LOOP
+               for(int chd = 0; chd < 16; chd++) {
+                       val[chd] = val[chd] * dac_pan[chd];
+               }
+               // Sign
+               __DECL_VECTORIZED_LOOP
+               for(int chd = 0; chd < 16; chd++) {
+                       dac_tmpval[chd] = val[chd] * sign[chd];
+               }
+               // Re-Init sample buffer
+               {
+               std::lock_guard<std::recursive_mutex> locker(m_locker);
+               if((sample_buffer != NULL) /*&& (sample_words < sample_length.load())*/){
+                       int32_t* np = &(sample_buffer[sample_pointer << 1]);
+                       __DECL_ALIGNED(8) int32_t lr[2];
+                       for(int i = 0; i < 2; i++) {
+                               lr[i] = 0;
                        }
-                       // Sign
-__DECL_VECTORIZED_LOOP
+                       // ADD or SUB
+                       __DECL_VECTORIZED_LOOP
                        for(int chd = 0; chd < 16; chd++) {
-                               dac_tmpval[chd] = (sign[chd]) ? -val[chd] : val[chd];
+                               lr[chd & 1] += dac_tmpval[chd];
                        }
-                       // Re-Init sample buffer
-                       if((sample_buffer != NULL) /*&& (sample_words < sample_length)*/){
-                               int32_t* np = &(sample_buffer[sample_pointer << 1]);
-                               __DECL_ALIGNED(8) int32_t lr[2];
-                               for(int i = 0; i < 2; i++) {
-                                       lr[i] = 0;
-                               }
-                               // ADD or SUB
-__DECL_VECTORIZED_LOOP
-                               for(int chd = 0; chd < 16; chd++) {
-                                       lr[chd & 1] += dac_tmpval[chd];
-                               }
 /*
-                       static const int32_t uplimit = 127 << 6;
-                       static const int32_t lowlimit  = -(127 << 6);
-__DECL_VECTORIZED_LOOP
-                               for(int chd = 0; chd < 2; chd++) {
-                                       if(lr[chd] > uplimit) {
-                                               lr[chd] = uplimit;
-                                       }
-                                       if(lr[chd] < lowlimit) {
-                                               lr[chd] = lowlimit;
-                                       }
-                                       lr[chd] >>= 2;
-                               }
+  static const int32_t uplimit = 127 << 6;
+  static const int32_t lowlimit  = -(127 << 6);
+  __DECL_VECTORIZED_LOOP
+  for(int chd = 0; chd < 2; chd++) {
+  if(lr[chd] > uplimit) {
+  lr[chd] = uplimit;
+  }
+  if(lr[chd] < lowlimit) {
+  lr[chd] = lowlimit;
+  }
+  lr[chd] >>= 2;
+  }
 */
-__DECL_VECTORIZED_LOOP
-                               for(int chd = 0; chd < 2; chd++) {
-                                       lr[chd] >>= 2;
-                               }
-                               np[0] = lr[0];
-                               np[1] = lr[1];
+                       __DECL_VECTORIZED_LOOP
+                       for(int chd = 0; chd < 2; chd++) {
+                               lr[chd] >>= 2;
                        }
-                       sample_pointer = (sample_pointer + 1) % sample_length;
+                       np[0] = lr[0];
+                       np[1] = lr[1];
+                       sample_pointer = (sample_pointer.load() + 1) % sample_length.load();
                        sample_words++;
-                       sample_words = (sample_words >= sample_length) ? sample_length : sample_words;
+                       sample_words = (sample_words.load() >= sample_length.load()) ? sample_length.load() : sample_words.load();
+               }
+               }
+       }
+}
+
+void RF5C68::write_signal(int ch, uint32_t data, uint32_t mask)
+{
+       switch(ch)
+       {
+       case SIG_RF5C68_DAC_PERIOD:
+               if(_RF5C68_DRIVEN_BY_EXTERNAL_CLOCK) {
+                       do_dac_period();
                }
                break;
        case SIG_RF5C68_CLEAR_INTR:
@@ -221,18 +252,7 @@ __DECL_VECTORIZED_LOOP
                write_signals(&interrupt_boundary, 0x80000008);
                break;
        case SIG_RF5C68_MUTE:
-               {
-                       bool old_is_mute = is_mute;
-                       is_mute = ((data & mask) != 0) ? true : false;
-                       if((is_mute != old_is_mute) && !(is_mute)) {
-                               sample_words = 0;
-                               sample_pointer = 0;
-                               read_pointer = 0;
-                               if((sample_buffer != NULL) && (sample_length > 0)) {
-                                       memset(sample_buffer, 0x00, sizeof(int32_t) * 2 * sample_length);
-                               }
-                       }
-               }
+               is_mute = ((data & mask) != 0) ? true : false;
                break;
        case SIG_RF5C68_REG_BANK:
                dac_bank = (data & 0x0f) << 12;
@@ -242,12 +262,28 @@ __DECL_VECTORIZED_LOOP
        }
 }
 
+
+
+void RF5C68::event_callback(int id,  int err)
+{
+       switch(id) {
+       case EVENT_DAC_PERIOD:
+               if(!(_RF5C68_DRIVEN_BY_EXTERNAL_CLOCK)) {
+                       do_dac_period();
+               }
+               break;
+       default:
+               break;
+       }
+}
+
 void RF5C68::write_io8(uint32_t addr, uint32_t data)
 {
        uint32_t naddr = addr & 0x0f;
        switch(naddr) {
        case 0x00: // ENV
-               dac_env[dac_ch] = data & 0xff;
+               dac_env[(dac_ch << 1) + 0] = data & 0xff;
+               dac_env[(dac_ch << 1) + 1] = data & 0xff;
 //             out_debug_log(_T("DAC REG 00 (ENV) CH=%d RAW=%02X"),
 //                                       dac_ch, data);
                break;
@@ -289,6 +325,21 @@ void RF5C68::write_io8(uint32_t addr, uint32_t data)
                {
                        bool old_dac_on = dac_on;
                        dac_on = ((data & 0x80) != 0) ? true : false;
+                       if(dac_on) {
+                               __UNLIKELY_IF((event_dac < 0) && !(_RF5C68_DRIVEN_BY_EXTERNAL_CLOCK)) {
+                                       register_event(this, EVENT_DAC_PERIOD,
+                                                                  1.0e6 / dac_rate, true, &event_dac);
+                               }
+                       } else {
+                               __UNLIKELY_IF(event_dac >= 0) {
+                                       cancel_event(this, event_dac);
+                               }
+                               __UNLIKELY_IF(event_lpf >= 0) {
+                                       cancel_event(this, event_lpf);
+                               }
+                               event_dac = -1;
+                               event_lpf = -1;
+                       }
                        if((data & 0x40) != 0) { // CB2-0
                                dac_ch = data & 0x07;
                        } else { // WB3-0
@@ -298,8 +349,8 @@ void RF5C68::write_io8(uint32_t addr, uint32_t data)
                                sample_pointer = 0;
                                sample_words = 0;
                                read_pointer = 0;
-                               if((sample_buffer != NULL) && (sample_length > 0)) {
-                                       memset(sample_buffer, 0x00, sizeof(int32_t) * 2 * sample_length);
+                               if((sample_buffer != NULL) && (sample_length.load() > 0)) {
+                                       memset(sample_buffer, 0x00, sizeof(int32_t) * 2 * sample_length.load());
                                }
                        }*/
                }
@@ -339,8 +390,11 @@ uint32_t RF5C68::read_io8(uint32_t addr)
 }
 
 // Read PCM memory
-uint32_t RF5C68::read_memory_mapped_io8(uint32_t addr)
+uint32_t RF5C68::read_memory_mapped_io8w(uint32_t addr, int* wait)
 {
+       __LIKELY_IF(wait != NULL) {
+               *wait = 6; // OK?
+       }
        __UNLIKELY_IF(addr >= 0x1000) return 0xff; // This is workaround.
        addr = (addr & 0xfff) | dac_bank;
        if(d_debugger != NULL && d_debugger->now_device_debugging) {
@@ -349,52 +403,27 @@ uint32_t RF5C68::read_memory_mapped_io8(uint32_t addr)
 //             if(dac_on) {
 //                     return 0xff;
 //             }
-               return read_via_debugger_data8(addr);
+               return wave_memory[addr];
        }
        return 0xff;
 }
 
-uint32_t RF5C68::read_memory_mapped_io16(uint32_t addr)
-{
-       __UNLIKELY_IF(addr >= 0x1000) return 0xffff; // This is workaround.
-       addr = (addr & 0xfff) | dac_bank;
-       if(d_debugger != NULL && d_debugger->now_device_debugging) {
-               return d_debugger->read_via_debugger_data16(addr);
-       } else {
-//             if(dac_on) {
-//                     return 0xffff;
-//             }
-               return read_via_debugger_data16(addr);
-       }
-       return 0xffff;
-}
 
-void RF5C68::write_memory_mapped_io8(uint32_t addr, uint32_t data)
+void RF5C68::write_memory_mapped_io8w(uint32_t addr, uint32_t data, int* wait)
 {
+       __LIKELY_IF(wait != NULL) {
+               *wait = 6; // OK?
+       }
        __UNLIKELY_IF(addr >= 0x1000) return; // This is workaround.
        addr = (addr & 0xfff) | dac_bank;
        // if(dac_on) don't write <- Is correct?
        if(d_debugger != NULL && d_debugger->now_device_debugging) {
                d_debugger->write_via_debugger_data8(addr, data);
        } else {
-//             if(!dac_on) {
-                       write_via_debugger_data8(addr, data);
-//                     return;
-//             }
-       }
-}
-
-void RF5C68::write_memory_mapped_io16(uint32_t addr, uint32_t data)
-{
-       __UNLIKELY_IF(addr >= 0x1000) return; // This is workaround.
-       addr = (addr & 0xfff) | dac_bank;
-       if(d_debugger != NULL && d_debugger->now_device_debugging) {
-               d_debugger->write_via_debugger_data16(addr, data);
-       } else {
-//             if(!dac_on) {
-                       write_via_debugger_data16(addr, data);
+//             if(dac_on) {
 //                     return;
 //             }
+               wave_memory[addr] = data;
        }
 }
 
@@ -402,39 +431,19 @@ uint32_t RF5C68::read_dma_data8w(uint32_t addr, int* wait)
 {
        __UNLIKELY_IF(addr >= 0x1000) return 0xff; // This is workaround.
        addr = (addr & 0xfff) | dac_bank;
-       uint32_t val = read_via_debugger_data8(addr);
+       uint32_t val = wave_memory[addr];
        __LIKELY_IF(wait != NULL) { // Normally Ignore DMA wait.
                *wait = 0;
        }
        return val;
 }
 
-uint32_t RF5C68::read_dma_data16w(uint32_t addr, int* wait)
-{
-       __UNLIKELY_IF(addr >= 0x1000) return 0xffff; // This is workaround.
-       addr = (addr & 0xfff) | dac_bank;
-       uint32_t val = read_via_debugger_data16(addr);
-       __LIKELY_IF(wait != NULL) { // Normally Ignore DMA wait.
-               *wait = 0;
-       }
-       return val;
-}
 
 void RF5C68::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
 {
        __UNLIKELY_IF(addr >= 0x1000) return; // This is workaround.
        addr = (addr & 0xfff) | dac_bank;
-       write_via_debugger_data8(addr, data);
-       __LIKELY_IF(wait != NULL) { // Normally Ignore DMA wait.
-               *wait = 0;
-       }
-}
-
-void RF5C68::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
-{
-       __UNLIKELY_IF(addr >= 0x1000) return; // This is workaround.
-       addr = (addr & 0xfff) | dac_bank;
-       write_via_debugger_data16(addr, data);
+       wave_memory[addr] = data;
        __LIKELY_IF(wait != NULL) { // Normally Ignore DMA wait.
                *wait = 0;
        }
@@ -449,32 +458,37 @@ void RF5C68::set_volume(int ch, int decibel_l, int decibel_r)
 
 void RF5C68::get_sample(int32_t *v, int words)
 {
-       if(words > sample_words) words = sample_words;
-       if(words <= 0) return;
-       if(v == NULL) return;
+       __UNLIKELY_IF(v == NULL) return;
+
+       int swords = sample_words.load();
+       __UNLIKELY_IF(words > swords) words = swords;
+       __UNLIKELY_IF(words <= 0) return;
+       int rptr = read_pointer.load();
        switch(words) {
        case 1:
-               v[2] = sample_buffer[(read_pointer << 1) + 0];
-               v[3] = sample_buffer[(read_pointer << 1) + 1];
+               v[0] = sample_buffer[(rptr << 1) + 0];
+               v[1] = sample_buffer[(rptr << 1) + 1];
                break;
        default:
                {
-                       int nptr = read_pointer - words + 1;
+                       int nptr = rptr - words + 1;
                        int nwords = words << 1;
-                       if(nptr < 0) nptr = read_pointer + sample_length - words;
+                       int slen = sample_length.load();
+                       if(nptr < 0) nptr = rptr + slen - words;
                        for(int i = 0; i < nwords; i += 2) {
                                v[i + 0] = sample_buffer[(nptr << 1) + 0];
                                v[i + 1] = sample_buffer[(nptr << 1) + 1];
-                               nptr = (nptr + 1) % sample_length;
+                               nptr = (nptr + 1) % slen;
                        }
                }
                break;
        }
+       return;
 }
 
 void RF5C68::lpf_threetap(int32_t *v, int &lval, int &rval)
 {
-       if(v == NULL) return ;
+       __UNLIKELY_IF(v == NULL) return ;
        static const int fact2 = 1800;
        static const int fact0 = 450;
        static const int fact4 = 4096 - (fact2 + fact0);
@@ -484,90 +498,105 @@ void RF5C68::lpf_threetap(int32_t *v, int &lval, int &rval)
 
 void RF5C68::mix(int32_t* buffer, int cnt)
 {
-
        int32_t lval, rval = 0;
-       int32_t lval2, rval2 = 0;
        // ToDo: supress pop noise.
-       if(cnt <= 0) return;
-       if(is_mute) return;
-
-       if((sample_buffer != NULL) && (sample_length > 0)) {
-               __DECL_ALIGNED(16) int32_t val[16] = {0}; // 0,1 : before / 2,3 : after
+       __UNLIKELY_IF(buffer == NULL) return;
+       __UNLIKELY_IF(cnt <= 0) return;
+       if(!(dac_on)) return;
+
+       int old_slen = sample_length.load();
+       bool need_load = true;
+       bool force_load = true;
+       if(old_slen > 0) {
+               __DECL_ALIGNED(16) int32_t val[16]; // 0,1 : before / 2,3 : after
+               mix_factor = lrint((dac_rate * 4096.0) / ((double)(mix_rate.load())));
+               int lval2, rval2 = 0;
                // ToDo: mix_freq <= dac_freq ; mix_factor >= 4096.
                if(mix_factor < 4096) {
-                       get_sample(val, 3);
-                       lpf_threetap(val, lval, rval);
                        for(int i = 0; i < (cnt << 1); i += 2) {
-                               int32_t interp_p = mix_count;
-                               int32_t interp_n = 4096 - mix_count;
-                               lval2 = (interp_p * (val[4] - lval)) >> 12;
-                               rval2 = (interp_p * (val[5] - rval)) >> 12;
-                               lval2 = lval + lval2;
-                               rval2 = rval + rval2;
-                               lval2 = apply_volume(lval2, volume_l) >> 1;
-                               rval2 = apply_volume(rval2, volume_r) >> 1;
                                // ToDo: interpoolate.
-                               buffer[i]     += lval2;
-                               buffer[i + 1] += rval2;
+                               if((force_load) || ((need_load) && (sample_words.load() > 0))) {
+                                       // Reload data
+                                       __DECL_VECTORIZED_LOOP
+                                       for(int ii = 0; ii < (sizeof(val) / sizeof(int32_t)); ii++) {
+                                               val[ii] = 0;
+                                       }
+                                       {
+                                               std::lock_guard<std::recursive_mutex> locker(m_locker);
+                                               get_sample(val, 3);
+                                       }
+                                       lpf_threetap(val, lval, rval);
+                                       #if 1
+                                       lastsample_l = apply_volume(lval, volume_l);
+                                       lastsample_r = apply_volume(rval, volume_r);
+                                       #endif
+                                       if(sample_words.load() >= 3) {
+                                               need_load = false;
+                                       }
+                                       force_load = false;
+                               }
+                               __LIKELY_IF(!(is_mute)) {
+                                       buffer[i]     += lastsample_l;
+                                       buffer[i + 1] += lastsample_r;
+                               }
                                mix_count += mix_factor;
                                if(mix_count >= 4096) {
+                                       std::lock_guard<std::recursive_mutex> locker(m_locker);
 //                             out_debug_log(_T("MIX COUNT=%d FACTOR=%d"), mix_count, mix_factor);
                                        int n = mix_count >> 12;
-                                       int old_rptr = read_pointer;
+                                       int old_rptr = read_pointer.load();
                                        read_pointer += n;
-                                       if((old_rptr < sample_pointer) && (read_pointer >= sample_pointer)) {
+                                       if((old_rptr < sample_pointer.load()) && (read_pointer.load() >= sample_pointer.load())) {
                                                // Overshoot read opinter
-                                               read_pointer = sample_pointer - 1;
-                                               if(read_pointer < 0) read_pointer = sample_length - 1;
-                                               if(read_pointer <= 0) read_pointer = 0;
-                                       } else if((old_rptr >= sample_pointer)) {
-                                               if(old_rptr < (sample_pointer + sample_length - sample_words)) {
-                                                       read_pointer = (sample_pointer + sample_length - sample_words);
+                                               read_pointer = sample_pointer.load() - 1;
+                                               if(read_pointer.load() < 0) read_pointer = sample_length.load() - 1;
+                                               if(read_pointer.load() <= 0) read_pointer = 0;
+                                       } else if((old_rptr >= sample_pointer.load())) {
+                                               if(old_rptr < (sample_pointer.load() + sample_length.load() - sample_words.load())) {
+                                                       read_pointer = (sample_pointer.load() + sample_length.load() - sample_words.load());
                                                }
                                        }
-                                       read_pointer = read_pointer % sample_length;
-                                       if(sample_words > 0) {
-                                               // Reload data
-                                               memset(val, 0x00, sizeof(val));
-                                               get_sample(val, 3);
-                                       } else {
-                                               val[0] = val[2];
-                                               val[1] = val[3];
-                                               val[2] = 0;
-                                               val[3] = 0;
-                                       }
-                                       lpf_threetap(val, lval, rval);
-//                             if(sample_words < 0) sample_words = 0;
+                                       read_pointer = read_pointer.load() % sample_length.load();
+                                       need_load = true;
                                        mix_count -= (n << 12);
                                }
                        }
                } else  if(mix_factor == 4096) {
                        // ToDo: Interpoolate
-                       get_sample(val, 4);
+                       {
+                               std::lock_guard<std::recursive_mutex> locker(m_locker);
+                               get_sample(val, 4);
+                       }
                        lpf_threetap(val, lval, rval);
                        for(int i = 0; i < (cnt << 1); i += 2) {
-                               lval2 = apply_volume(lval, volume_l) >> 1;
-                               rval2 = apply_volume(rval, volume_r) >> 1;
-                               buffer[i]     += lval2;
-                               buffer[i + 1] += rval2;
-                               read_pointer = (read_pointer + 1) % sample_length;
-                               get_sample(val, 4);
+                               lastsample_l = apply_volume(lval, volume_l) >> 1;
+                               lastsample_r = apply_volume(rval, volume_r) >> 1;
+                               buffer[i]     += lastsample_l;
+                               buffer[i + 1] += lastsample_r;
+                               read_pointer = (read_pointer.load() + 1) % sample_length;
+                               {
+                                       std::lock_guard<std::recursive_mutex> locker(m_locker);
+                                       get_sample(val, 4);
+                               }
                                lpf_threetap(val, lval, rval);
                        }
                } else { // MIX_FACTOR > 1.0
                        // ToDo: Correct downsampling.
-                       get_sample(val, 8);
+                       {
+                               std::lock_guard<std::recursive_mutex> locker(m_locker);
+                               get_sample(val, 8);
+                       }
                        lpf_threetap(val, lval, rval);
                        for(int i = 0; i < (cnt << 1); i += 2) {
-                               lval2 = apply_volume(lval, volume_l) >> 1;
-                               rval2 = apply_volume(rval, volume_r) >> 1;
-                               buffer[i]     += lval2;
-                               buffer[i + 1] += rval2;
+                               lastsample_l = apply_volume(lval, volume_l) >> 1;
+                               lastsample_r = apply_volume(rval, volume_r) >> 1;
+                               buffer[i]     += lastsample_l;
+                               buffer[i + 1] += lastsample_r;
 
                                int n = mix_count >> 12;
                                read_pointer += n;
-                               read_pointer = read_pointer % sample_length;
-                               if(sample_words > 0) {
+                               read_pointer = read_pointer.load() % sample_length.load();
+                               if(sample_words.load() > 0) {
                                        // Reload data
                                        memset(val, 0x00, sizeof(val));
                                        get_sample(val, 8);
@@ -586,10 +615,11 @@ void RF5C68::mix(int32_t* buffer, int cnt)
 
 void RF5C68::initialize_sound(int sample_rate, int samples)
 {
+       std::lock_guard<std::recursive_mutex> locker(m_locker);
        if((sample_rate > 0) && (samples > 0)) {
                mix_rate = sample_rate;
                sample_length = samples;
-               mix_factor = (int)(dac_rate * 4096.0 / (double)mix_rate);
+               //mix_factor = set_mix_factor(dac_rate, mix_rate);
                mix_count = 0;
                read_pointer = 0;
                sample_pointer = 0;
@@ -600,7 +630,6 @@ void RF5C68::initialize_sound(int sample_rate, int samples)
                if(sample_buffer != NULL) {
                        memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
                }
-               sample_tick_us = 1.0e6 / ((double)mix_rate);
        } else {
                if(sample_buffer != NULL) {
                        free(sample_buffer);
@@ -608,7 +637,6 @@ void RF5C68::initialize_sound(int sample_rate, int samples)
                sample_buffer = NULL;
                sample_length = 0;
                mix_rate = 1;
-               sample_tick_us = 0.0;
        }
 }
 
@@ -623,40 +651,6 @@ uint32_t RF5C68::read_debug_data8(uint32_t addr)
 }
 
 
-void RF5C68::write_via_debugger_data8(uint32_t addr, uint32_t data)
-{
-       wave_memory[addr] = data;
-}
-
-void RF5C68::write_via_debugger_data16(uint32_t addr, uint32_t data)
-{
-       pair16_t _b;
-       _b.w = data;
-       __LIKELY_IF(addr < 0xffff) {
-               _b.write_2bytes_le_to(&(wave_memory[addr]));
-       } else {
-               _b.b.l = wave_memory[addr] = _b.b.l;
-       }
-}
-
-
-uint32_t RF5C68::read_via_debugger_data8(uint32_t addr)
-{
-       return wave_memory[addr];
-}
-
-uint32_t RF5C68::read_via_debugger_data16(uint32_t addr)
-{
-       pair16_t _b;
-       __LIKELY_IF(addr < 0xffff) {
-               _b.read_2bytes_le_from(&(wave_memory[addr]));
-       } else {
-               _b.b.l = wave_memory[addr + 0];
-               _b.b.h = 0xff;
-       }
-       return _b.w;
-}
-
 bool RF5C68::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
 {
        _TCHAR sbuf[8][512] = {0};
@@ -665,7 +659,7 @@ bool RF5C68::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
                my_stprintf_s(sbuf[i], sizeof(sbuf[i]),
                                          _T("CH%d: %s: ENV=%02X LPAN=%02X RPAN=%02X FD=%04X LS=%04X ADDR=%08X ADDR_ST=%08X\n")
                                          , i, (dac_onoff[i]) ? _T("ON ") : _T("OFF")
-                                         , dac_env[i], dac_pan[(i << 1) + 0], dac_pan[(i << 1) + 1]
+                                         , dac_env[i << 1], dac_pan[(i << 1) + 0], dac_pan[(i << 1) + 1]
                                          , dac_fd[i].w.l, dac_ls[i].w.l
                                          , dac_addr[i], dac_addr_st[i].w.l
                        );
@@ -681,7 +675,7 @@ bool RF5C68::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
        return true;
 }
 
-#define STATE_VERSION  1
+#define STATE_VERSION  3
 
 bool RF5C68::process_state(FILEIO* state_fio, bool loading)
 {
@@ -698,48 +692,63 @@ bool RF5C68::process_state(FILEIO* state_fio, bool loading)
        state_fio->StateArray(dac_onoff, sizeof(dac_onoff), 1);
        state_fio->StateArray(dac_addr_st, sizeof(dac_addr_st), 1);
        state_fio->StateArray(dac_addr, sizeof(dac_addr), 1);
-       state_fio->StateArray(dac_env, sizeof(dac_env), 1);
+
+       uint32_t env_bak[8];
+       for(int ii = 0; ii < 8; ii++) {
+               env_bak[ii] = dac_env[ii << 1];
+       }
+       state_fio->StateArray(env_bak, sizeof(env_bak), 1);
+       if(loading) {
+               for(int ii = 0; ii < 8; ii++) {
+                       dac_env[(ii << 1) + 0] = env_bak[ii];
+                       dac_env[(ii << 1) + 1] = env_bak[ii];
+               }
+       }
+
        state_fio->StateArray(dac_pan, sizeof(dac_pan), 1);
        state_fio->StateArray(dac_ls, sizeof(dac_ls), 1);
        state_fio->StateArray(dac_fd, sizeof(dac_fd), 1);
        state_fio->StateArray(dac_force_load, sizeof(dac_force_load), 1);
        state_fio->StateArray(dac_tmpval, sizeof(dac_tmpval), 1);
 
-//     state_fio->StateValue(sample_words);
-//     state_fio->StateValue(sample_pointer);
-//     state_fio->StateValue(read_pointer);
+       // These vars use std::atmic<int> , below are workaround.
+       int sample_words_tmp = sample_words;
+       int sample_pointer_tmp = sample_pointer;
+       int read_pointer_tmp = read_pointer;
+
+       state_fio->StateValue(sample_words_tmp);
+       state_fio->StateValue(sample_pointer_tmp);
+       state_fio->StateValue(read_pointer_tmp);
+       if(loading) {
+               sample_words = sample_words_tmp;
+               sample_pointer = sample_pointer_tmp;
+               read_pointer = read_pointer_tmp;
+       }
+
 //     int sample_length_old = sample_length;
 //     state_fio->StateValue(sample_length);
 
 //     state_fio->StateValue(mix_factor);
-//     state_fio->StateValue(mix_count);
+       state_fio->StateValue(mix_count);
        state_fio->StateValue(dac_rate);
+       state_fio->StateValue(lpf_cutoff);
+
+       state_fio->StateValue(lastsample_l);
+       state_fio->StateValue(lastsample_r);
 
        state_fio->StateArray(wave_memory, sizeof(wave_memory), 1);
 
        // ToDo: Save/Load sample_buffer.
        // Post Process
        if(loading) {
+               std::lock_guard<std::recursive_mutex> locker(m_locker);
                // ToDo: load sample_length & sample_buffer.
-               if(mix_rate > 0) {
-                       sample_tick_us = 1.0e6 / ((double)mix_rate);
-                       mix_factor = (int)(dac_rate * 4096.0 / (double)mix_rate);
-                       mix_count = 0;
-               } else {
-                       sample_tick_us = 0;
-                       mix_count = 0;
-                       mix_factor = 0;
-               }
-               read_pointer = 0;
-               sample_pointer = 0;
-               sample_words = 0;
-
                if(sample_buffer != NULL) free(sample_buffer);
                sample_buffer = NULL;
-               if(sample_length > 0) {
-                       sample_buffer = (int32_t*)malloc(sample_length * sizeof(int32_t) * 2);
+               if(sample_length.load() > 0) {
+                       sample_buffer = (int32_t*)malloc(sample_length.load() * sizeof(int32_t) * 2);
                        if(sample_buffer != NULL) {
-                               memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
+                               memset(sample_buffer, 0x00, sample_length.load() * sizeof(int32_t) * 2);
                        }
                }
        } else { // Saving
index 2bea8fe..f7cef12 100644 (file)
@@ -11,6 +11,9 @@
     I/O: 0-8
     MEMORY: 64KB (banked per 4kb).
 */
+#include <atomic>
+#include <mutex>
+
 #include "../device.h"
 #include "../../common.h"
 
@@ -45,16 +48,24 @@ protected:
        bool is_mute;
 
        double dac_rate;
+       double lpf_cutoff;
        int mix_factor;
        int mix_count;
-       int sample_words;
-       int sample_pointer;
-       int read_pointer;
+
+       int lastsample_l;
+       int lastsample_r;
+
+       bool _RF5C68_DRIVEN_BY_EXTERNAL_CLOCK;
+
+       std::recursive_mutex m_locker;
+       std::atomic<int> sample_words;
+       std::atomic<int> sample_pointer;
+       std::atomic<int> read_pointer;
 
        __DECL_ALIGNED(16) bool dac_onoff[8];
        __DECL_ALIGNED(16) pair32_t dac_addr_st[8];
        __DECL_ALIGNED(16) uint32_t dac_addr[8];
-       __DECL_ALIGNED(16) uint32_t dac_env[8];
+       __DECL_ALIGNED(16) uint32_t dac_env[16];
        __DECL_ALIGNED(16) uint32_t dac_pan[16];
        __DECL_ALIGNED(16) pair32_t dac_ls[8];
        __DECL_ALIGNED(16) pair32_t dac_fd[8];
@@ -64,32 +75,34 @@ protected:
        bool dac_force_load[8];
        __DECL_ALIGNED(16) int32_t  dac_tmpval[16];
 
-       int volume_l, volume_r;
+       std::atomic<int> volume_l, volume_r;
        int32_t* sample_buffer;
 
-       int sample_length;
+       std::atomic<int> sample_length;
+       std::atomic<int> mix_rate;
 
-       int mix_rate;
-       double sample_tick_us;
+       int event_dac;
+       int event_lpf;
 
        // ToDo: Work correct LPF.
 
+       virtual void do_dac_period();
+
        virtual void __FASTCALL get_sample(int32_t *v, int words);
        void __FASTCALL lpf_threetap(int32_t *v, int &lval, int &rval);
 
 public:
        RF5C68(VM_TEMPLATE* parent_vm, EMU_TEMPLATE* parent_emu) : DEVICE(parent_vm, parent_emu)
        {
-               volume_l = volume_r = 1024;
                sample_buffer = NULL;
                sample_length = 0;
-               mix_rate = 1; // For Error
-               sample_tick_us = 0.0;
-               is_mute = true;
+               mix_rate = 48000; // For Error
                initialize_output_signals(&interrupt_boundary);
                d_debugger = NULL;
 
-               dac_rate = 8.0e6 / 384;
+               dac_rate = 8.0e6 / 384; // About 19.2KHz
+               lpf_cutoff = 4.0e3;
+               _RF5C68_DRIVEN_BY_EXTERNAL_CLOCK = false;
                set_device_name(_T("ADPCM RF5C68"));
        }
        ~RF5C68() {}
@@ -99,17 +112,13 @@ public:
 
        virtual void reset() override;
 
-       virtual uint32_t __FASTCALL read_memory_mapped_io8(uint32_t addr) override;
-       virtual uint32_t __FASTCALL read_memory_mapped_io16(uint32_t addr) override;
+       virtual void __FASTCALL event_callback(int id, int err) override;
 
-       virtual void __FASTCALL write_memory_mapped_io8(uint32_t addr, uint32_t data) override;
-       virtual void __FASTCALL write_memory_mapped_io16(uint32_t addr, uint32_t data) override;
+       virtual uint32_t __FASTCALL read_memory_mapped_io8w(uint32_t addr, int* wait) override;
+       virtual void __FASTCALL write_memory_mapped_io8w(uint32_t addr, uint32_t data, int* wait) override;
 
        virtual uint32_t __FASTCALL read_dma_data8w(uint32_t addr, int* wait) override;
-       virtual uint32_t __FASTCALL read_dma_data16w(uint32_t addr, int* wait) override;
        virtual void __FASTCALL write_dma_data8w(uint32_t addr, uint32_t data, int* wait) override;
-       virtual void __FASTCALL write_dma_data16w(uint32_t addr, uint32_t data, int* wait) override;
-
        virtual uint32_t  __FASTCALL read_debug_data8(uint32_t addr) override;
        virtual void __FASTCALL write_debug_data8(uint32_t addr, uint32_t data) override;
 
@@ -121,11 +130,6 @@ public:
 
        virtual bool get_debug_regs_info(_TCHAR *buffer, size_t buffer_len) override;
 
-       virtual uint32_t __FASTCALL read_via_debugger_data8(uint32_t addr) override;
-       virtual uint32_t __FASTCALL read_via_debugger_data16(uint32_t addr) override;
-       virtual void __FASTCALL write_via_debugger_data16(uint32_t addr, uint32_t data) override;
-       virtual void __FASTCALL write_via_debugger_data8(uint32_t addr, uint32_t data) override;
-
        void *get_debugger() override
        {
                return d_debugger;
@@ -146,13 +150,20 @@ public:
          unique functions
        */
        virtual void initialize_sound(int sample_rate, int samples);
+
+       virtual void set_lpf_cutoff(double freq)
+       {
+               lpf_cutoff = freq;
+               //      calc_lpf_cutoff(freq);
+       }
        virtual void set_dac_rate(double freq)
        {
                dac_rate = freq;
                sample_words = 0;
                sample_pointer = 0;
-               mix_factor = (int)(dac_rate * 4096.0 / (double)mix_rate);
+               //mix_factor = set_mix_factor(dac_rate, mix_rate);
                mix_count = 0;
+               //calc_lpf_cutoff(lpf_cutoff);
                if((sample_buffer != NULL) && (sample_length > 0)) {
                        memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
                }
@@ -161,7 +172,6 @@ public:
        {
                d_debugger = device;
        }
-
        void set_context_interrupt_boundary(DEVICE* device, int id, uint32_t mask)
        {
                register_output_signal(&interrupt_boundary, device, id, mask);