X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2F32x%2Fpwm.c;h=0e7307829175b33b15284fa6ed46676ad5f73ac8;hb=1d7a28a723d59da67b58e42a61bc9f1905044fd5;hp=9475c004ccb901c0ef00555d065c6e278b27e569;hpb=236990cf7712bf4c2b46d06842c4f5f037e83328;p=picodrive.git diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index 9475c00..0e73078 100644 --- a/pico/32x/pwm.c +++ b/pico/32x/pwm.c @@ -6,11 +6,14 @@ static int pwm_mult; static int pwm_ptr; int pwm_frame_smp_cnt; +static int timer_line_ticks[2]; -void p32x_pwm_refresh(void) +// timers. This includes PWM timer in 32x and internal SH2 timers +void p32x_timers_recalc(void) { int cycles = Pico32x.regs[0x32 / 2]; int frame_samples; + int tmp, i; cycles = (cycles - 1) & 0x0fff; if (cycles < 500) { @@ -25,22 +28,56 @@ void p32x_pwm_refresh(void) frame_samples = OSC_NTSC / 7 * 3 / 60 / cycles; pwm_line_samples = (frame_samples << 16) / scanlines_total; + + // SH2 timer step + for (i = 0; i < 2; i++) { + tmp = PREG8(Pico32xMem->sh2_peri_regs[i], 0x80) & 7; + // Sclk cycles per timer tick + if (tmp) + cycles = 0x20 << tmp; + else + cycles = 2; + if (Pico.m.pal) + tmp = OSC_PAL / 7 * 3 / 50 / scanlines_total; + else + tmp = OSC_NTSC / 7 * 3 / 60 / scanlines_total; + timer_line_ticks[i] = (tmp << 16) / cycles; + elprintf(EL_32X, "timer_line_ticks[%d] = %.3f", i, (double)timer_line_ticks[i] / 0x10000); + } } -// irq for every sample?? -// FIXME: we need to hit more than once per line :( -void p32x_pwm_irq_check(int new_line) +// PWM irq for every tm samples +void p32x_timers_do(int new_line) { - int tm = (Pico32x.regs[0x30 / 2] & 0x0f00) >> 8; - if (tm == 0) - return; // TODO: verify - - if (new_line) - Pico32x.pwm_irq_sample_cnt += pwm_line_samples; - if (Pico32x.pwm_irq_sample_cnt >= (tm << 16)) { - Pico32x.pwm_irq_sample_cnt -= tm << 16; - Pico32x.sh2irqs |= P32XI_PWM; - p32x_update_irls(); + int tm, cnt, i; + tm = (Pico32x.regs[0x30 / 2] & 0x0f00) >> 8; + if (tm != 0) { + if (new_line) + Pico32x.pwm_irq_sample_cnt += pwm_line_samples; + if (Pico32x.pwm_irq_sample_cnt >= (tm << 16)) { + Pico32x.pwm_irq_sample_cnt -= tm << 16; + Pico32x.sh2irqs |= P32XI_PWM; + p32x_update_irls(); + } + } + + if (!new_line) + return; + + for (i = 0; i < 2; i++) { + void *pregs = Pico32xMem->sh2_peri_regs[i]; + if (PREG8(pregs, 0x80) & 0x20) { // TME + cnt = PREG8(pregs, 0x81); + cnt += timer_line_ticks[i]; + if (cnt >= 0x100) { + int level = PREG8(pregs, 0xe3) >> 4; + int vector = PREG8(pregs, 0xe4) & 0x7f; + elprintf(EL_32X, "%csh2 WDT irq (%d, %d)", i ? 's' : 'm', level, vector); + sh2_internal_irq(&sh2s[i], level, vector); + } + cnt &= 0xff; + PREG8(pregs, 0x81) = cnt; + } } } @@ -78,7 +115,7 @@ void p32x_pwm_write16(unsigned int a, unsigned int d) Pico32x.regs[0x30 / 2] = d; else if (a == 2) { // cycle Pico32x.regs[0x32 / 2] = d & 0x0fff; - p32x_pwm_refresh(); + p32x_timers_recalc(); Pico32x.pwm_irq_sample_cnt = 0; // resets? } else if (a <= 8) {