X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2F32x%2Fpwm.c;h=0e7307829175b33b15284fa6ed46676ad5f73ac8;hb=52d759c30f640f4af451eb7811e507ddece0e360;hp=102794b0ca9a109b33fafe80a18bf81cad655d36;hpb=db1d3564e69b422518701926bffdeae05379c400;p=picodrive.git diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index 102794b..0e73078 100644 --- a/pico/32x/pwm.c +++ b/pico/32x/pwm.c @@ -6,15 +6,18 @@ 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) { - elprintf(EL_32X|EL_ANOMALY, "pwm: low cycle value: %d", cycles + 1); + elprintf(EL_32X|EL_PWM|EL_ANOMALY, "pwm: low cycle value: %d", cycles + 1); cycles = 500; } pwm_cycles = cycles; @@ -25,21 +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(void) +// 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 - - 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; + } } } @@ -58,7 +96,7 @@ unsigned int p32x_pwm_read16(unsigned int a) case 6: // R ch case 8: // MONO predict = (pwm_line_samples * Pico.m.scanline) >> 16; - elprintf(EL_32X, "pwm: read status: ptr %d/%d, predict %d", + elprintf(EL_PWM, "pwm: read status: ptr %d/%d, predict %d", pwm_frame_smp_cnt, (pwm_line_samples * scanlines_total) >> 16, predict); if (pwm_frame_smp_cnt > predict + 3) d |= P32XP_FULL; @@ -77,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) { @@ -96,7 +134,7 @@ void p32x_pwm_write16(unsigned int a, unsigned int d) if (a >= 6) { // R or MONO pwm_frame_smp_cnt++; pwm_ptr = (pwm_ptr + 1) & (PWM_BUFF_LEN - 1); - elprintf(EL_32X, "pwm: smp_cnt %d, ptr %d, smp %x", pwm_frame_smp_cnt, pwm_ptr, d); + elprintf(EL_PWM, "pwm: smp_cnt %d, ptr %d, smp %x", pwm_frame_smp_cnt, pwm_ptr, d); } } } @@ -136,7 +174,7 @@ void p32x_pwm_update(int *buf32, int length, int stereo) } } - elprintf(EL_STATUS, "pwm_update: pwm_ptr %d, len %d, step %04x, done %d", + elprintf(EL_PWM, "pwm_update: pwm_ptr %d, len %d, step %04x, done %d", pwm_ptr, length, step, (pwmb - Pico32xMem->pwm) / 2); pwm_ptr = 0;