32x, configurable pwm irq optimization to reduce pwm irq load
authorkub <derkub@gmail.com>
Thu, 10 Oct 2019 22:02:23 +0000 (00:02 +0200)
committerkub <derkub@gmail.com>
Thu, 10 Oct 2019 22:56:32 +0000 (00:56 +0200)
pico/32x/pwm.c
pico/pico.h
platform/common/menu_pico.c
platform/common/menu_pico.h

index 0aa2f58..3e5ce0a 100644 (file)
@@ -14,13 +14,18 @@ static struct {
   int irq_reload;
   int doing_fifo;
   int silent;
+  int irq_timer;
+  int irq_state;
   short current[2];
 } pwm;
 
+enum { PWM_IRQ_LOCKED, PWM_IRQ_STOPPED, PWM_IRQ_LOW, PWM_IRQ_HIGH };
+
 void p32x_pwm_ctl_changed(void)
 {
   int control = Pico32x.regs[0x30 / 2];
   int cycles = Pico32x.regs[0x32 / 2];
+  int pwm_irq_opt = PicoIn.opt & POPT_PWM_IRQ_OPT;
 
   cycles = (cycles - 1) & 0x0fff;
   pwm.cycles = cycles;
@@ -31,8 +36,10 @@ void p32x_pwm_ctl_changed(void)
   if ((control & 0x0f) != 0)
     pwm.mult = 0x10000 / cycles;
 
-  pwm.irq_reload = (control & 0x0f00) >> 8;
-  pwm.irq_reload = ((pwm.irq_reload - 1) & 0x0f) + 1;
+  pwm.irq_timer = (control & 0x0f00) >> 8;
+  pwm.irq_timer = ((pwm.irq_timer - 1) & 0x0f) + 1;
+  pwm.irq_reload = pwm.irq_timer;
+  pwm.irq_state = pwm_irq_opt ? PWM_IRQ_STOPPED: PWM_IRQ_LOCKED;
 
   if (Pico32x.pwm_irq_cnt == 0)
     Pico32x.pwm_irq_cnt = pwm.irq_reload;
@@ -104,6 +111,11 @@ static void consume_fifo_do(SH2 *sh2, unsigned int m68k_cycles,
     if (--Pico32x.pwm_irq_cnt == 0) {
       Pico32x.pwm_irq_cnt = pwm.irq_reload;
       do_pwm_irq(sh2, m68k_cycles);
+    } else if (Pico32x.pwm_p[1] == 0 && pwm.irq_state >= PWM_IRQ_LOW) {
+      // buffer underrun. Reduce reload rate if above programmed setting.
+      if (pwm.irq_reload > pwm.irq_timer)
+        pwm.irq_reload--;
+      pwm.irq_state = PWM_IRQ_LOW;
     }
   }
   Pico32x.pwm_cycle_p = m68k_cycles * 3 - sh2_cycles_diff;
@@ -221,10 +233,22 @@ void p32x_pwm_write16(unsigned int a, unsigned int d,
     case 6/2: // R ch
       fifo = Pico32xMem->pwm_fifo[1];
       idx = Pico32xMem->pwm_index[1];
-      if (Pico32x.pwm_p[1] < 3)
+      if (Pico32x.pwm_p[1] < 3) {
+        if (pwm.irq_state == PWM_IRQ_STOPPED)
+          pwm.irq_state = PWM_IRQ_LOW;
+        if (Pico32x.pwm_p[1] == 2 && pwm.irq_state >= PWM_IRQ_LOW) {
+          // buffer full. If there was no buffer underrun after last fill,
+          // try increasing reload rate to reduce IRQs
+          if (pwm.irq_reload < 3 && pwm.irq_state == PWM_IRQ_HIGH)
+            pwm.irq_reload ++;
+          pwm.irq_state = PWM_IRQ_HIGH;
+        }
         Pico32x.pwm_p[1]++;
-      else {
-//        fifo[(idx+1) % 4] = fifo[idx];
+      } else {
+        // buffer overflow. Some roms always fill the complete buffer even if
+        // reload rate is set below max. Lock reload rate to programmed setting.
+        pwm.irq_reload = pwm.irq_timer;
+        pwm.irq_state = PWM_IRQ_LOCKED;
         idx = (idx+1) % 4;
         Pico32xMem->pwm_index[0] = idx;
       }
@@ -236,7 +260,6 @@ void p32x_pwm_write16(unsigned int a, unsigned int d,
       if (Pico32x.pwm_p[0] < 3)
         Pico32x.pwm_p[0]++;
       else {
-//        fifo[(idx+1) % 4] = fifo[idx];
         idx = (idx+1) % 4;
         Pico32xMem->pwm_index[0] = idx;
       }
index ac1550d..a9359a1 100644 (file)
@@ -72,6 +72,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
 #define POPT_DIS_IDLE_DET   (1<<19)\r
 #define POPT_EN_32X         (1<<20)\r
 #define POPT_EN_PWM         (1<<21)\r
+#define POPT_PWM_IRQ_OPT    (1<<22)\r
 \r
 #define PAHW_MCD  (1<<0)\r
 #define PAHW_32X  (1<<1)\r
index 7b0cd78..9fb3142 100644 (file)
@@ -506,6 +506,7 @@ static menu_entry e_menu_adv_options[] =
        mee_onoff     ("Disable frame limiter",    MA_OPT2_NO_FRAME_LIMIT,currentConfig.EmuOpt, EOPT_NO_FRMLIMIT),
        mee_onoff     ("Enable dynarecs",          MA_OPT2_DYNARECS,      PicoIn.opt, POPT_EN_DRC),
        mee_onoff     ("Status line in main menu", MA_OPT2_STATUS_LINE,   currentConfig.EmuOpt, EOPT_SHOW_RTC),
+       mee_onoff     ("PWM IRQ optimization",     MA_OPT2_PWM_IRQ_OPT,   PicoIn.opt, POPT_PWM_IRQ_OPT),
        MENU_OPTIONS_ADV
        mee_end,
 };
index 595989e..c626c77 100644 (file)
@@ -58,6 +58,7 @@ typedef enum
        MA_OPT2_NO_SPRITE_LIM,
        MA_OPT2_NO_IDLE_LOOPS,
        MA_OPT2_OVERCLOCK_M68K,
+       MA_OPT2_PWM_IRQ_OPT,
        MA_OPT2_DONE,
        MA_OPT3_SCALE,          /* psp (all OPT3) */
        MA_OPT3_HSCALE32,