X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2F32x%2Fpwm.c;h=8e365892689d604bdc263d8373fe6b70c320c7eb;hb=1f1ff763e661bab664151c4821c65dad35777976;hp=bde979587c91ee44e1fd9e49f22b725cbe4ffea5;hpb=be20816c4c487c4b114aa444b1a5819d5785b118;p=picodrive.git diff --git a/pico/32x/pwm.c b/pico/32x/pwm.c index bde9795..8e36589 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,22 +28,60 @@ 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 line_call) { - 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; + + if (PicoOpt & POPT_EN_PWM) + { + tm = (Pico32x.regs[0x30 / 2] & 0x0f00) >> 8; + if (tm != 0) { + if (line_call) + 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(!line_call); + } + } + } + + if (!line_call) + 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; + } } } @@ -59,7 +100,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; @@ -78,7 +119,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) { @@ -97,7 +138,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); } } } @@ -137,7 +178,7 @@ void p32x_pwm_update(int *buf32, int length, int stereo) } } - elprintf(EL_32X, "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;