From 20d2358ab1f25608ee1ea067007e10a1e266b811 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 11 Oct 2019 00:02:23 +0200 Subject: [PATCH] 32x, configurable pwm irq optimization to reduce pwm irq load --- pico/32x/pwm.c | 35 +++++++++++++++++++++++++++++------ pico/pico.h | 1 + platform/common/menu_pico.c | 1 + platform/common/menu_pico.h | 1 + 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index 0aa2f586..3e5ce0ae 100644 --- a/pico/32x/pwm.c +++ b/pico/32x/pwm.c @@ -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; } diff --git a/pico/pico.h b/pico/pico.h index ac1550d4..a9359a18 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -72,6 +72,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s; #define POPT_DIS_IDLE_DET (1<<19) #define POPT_EN_32X (1<<20) #define POPT_EN_PWM (1<<21) +#define POPT_PWM_IRQ_OPT (1<<22) #define PAHW_MCD (1<<0) #define PAHW_32X (1<<1) diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 7b0cd78c..9fb31426 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -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, }; diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index 595989e8..c626c772 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -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, -- 2.39.2