diff --git a/main.c b/main.c index 3d0f4aa..30fb881 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,7 @@ #include "vdp1.h" #include "scu.h" #include "smpc.h" +#include "sh2.h" void fill_32(u32 * buf, u32 v, s32 n) { @@ -16,9 +17,13 @@ void timer0_int(void) __attribute__ ((interrupt_handler)); void timer0_int(void) { scu.reg.IST &= ~(IST__TIMER0); +} - // The SMPC uses the V-BLANK-IN interrupt to execute internal tasks. At this - // time, issuing commands for 300 µs from V-BLANK-IN is prohibited. +void oci_int(void) __attribute__ ((interrupt_handler)); +void oci_int(void) +{ + // clear OCFA + sh2.reg.FTCSR &= ~(FTCSR__OCFA); while (smpc.reg.SF != 0) {} @@ -193,10 +198,53 @@ void start(void) vec[SCU_VEC__TIMER0] = (u32)(&timer0_int); vec[SCU_VEC__SMPC] = (u32)(&smpc_int); - scu.reg.T0C = 5; - scu.reg.T1MD = T1MD__TENB; + //scu.reg.T0C = 5; + //scu.reg.T1MD = T1MD__TENB; + + // From the SMPC manual: + // The SMPC uses the V-BLANK-IN interrupt to execute internal tasks. At this + // time, issuing commands for 300 µs from V-BLANK-IN is prohibited. + + // CLKCHG320 (power-on default) NTSC, the FRC's internal clock is 26.8741 MHz. + // The possible periods are then: + // + // - 0.29768 µs (/8) + // - 1.19074 µs (/32) + // - 4.76295 µs (/128) + // + // (1/(26.8741 MHz)) * 128 * 63 = 300.066 µs + + // FRC, OCRA, OCRB, and FCIR are 16-bit registers, but the FRT bus is an 8-bit + // bus. + + // TCR set CKS to /128 + // TOCR set OCRS to OCRA + // TIER set OCIAE + // FTCSR set CCLRA (clear FRC on compare match A) + // VCRC set FOCV + // OCRA set 63 + // FRC set 0 + + vec[0x60] = (u32)&oci_int; + sh2.reg.VCRC = VCRC__FOCV(0x60); + + sh2.reg.TCR = TCR__CKS__INTERNAL_DIV128; + sh2.reg.TOCR = TOCR__OCRS__OCRA; + sh2.reg.FTCSR = FTCSR__CCLRA; + sh2.reg.OCRAB.H = 0; // Even though Kronos doesn't emulate this, SH7095 says + // we are required to write the upper bit prior to + // writing the lower byte + sh2.reg.OCRAB.L = 63; + sh2.reg.FRC.H = 0; + sh2.reg.FRC.L = 0; + + // enable output compare interrupt + sh2.reg.TIER = TIER__OCIAE; + + // reset/enable interrupts + scu.reg.IST = 0; - scu.reg.IMS = ~(IMS__TIMER0 | IMS__SMPC); + scu.reg.IMS = ~(IMS__SMPC); while (1) { vec[0] = scu.reg.IST; diff --git a/scu.h b/scu.h index ec30845..1bd78bb 100644 --- a/scu.h +++ b/scu.h @@ -160,5 +160,3 @@ enum scu_vec { }; static_assert(SCU_VEC__EXT15 == 0x5f); - -extern reg32 vec[0x60] __asm("vec"); diff --git a/sh2.h b/sh2.h index 5922bee..540d8bb 100644 --- a/sh2.h +++ b/sh2.h @@ -10,11 +10,20 @@ typedef struct sh2_reg { reg8 _res0[10]; reg8 TIER; // 0x010 reg8 FTCSR; // 0x011 - reg16 FRC; // 0x012 - reg16 OCRA_B; // 0x014 + struct { + reg8 H; // 0x012 + reg8 L; // 0x013 + } FRC; + struct { + reg8 H; // 0x014 + reg8 L; // 0x015 + } OCRAB; reg8 TCR; // 0x016 reg8 TOCR; // 0x017 - reg16 FICR; // 0x018 + struct { + reg8 H; // 0x018 + reg8 L; // 0x018 + } FICR; reg8 _res1[70]; reg16 IPRB; // 0x060 reg16 VCRA; // 0x062 @@ -87,7 +96,7 @@ typedef struct sh2_reg { } sh2_reg; static_assert((sizeof (struct sh2_reg)) == 0x200); -static_assert((offsetof (struct sh2_reg, OCRA_B)) == 0x014); +static_assert((offsetof (struct sh2_reg, OCRAB)) == 0x014); static_assert((offsetof (struct sh2_reg, BCR1)) == 0x1e0); struct sh2 { @@ -95,3 +104,47 @@ struct sh2 { }; extern struct sh2 sh2 __asm("sh2"); + +extern reg32 vec[0xff] __asm("vec"); + +enum tier_bits { + TIER__ICIE = (1 << 7), + TIER__OCIAE = (1 << 3), + TIER__OCIBE = (1 << 2), + TIER__OVIE = (1 << 1), +}; +enum ftcsr_bits { + FTCSR__ICF = (1 << 7), + FTCSR__OCFA = (1 << 3), + FTCSR__OCFB = (1 << 2), + FTCSR__OVF = (1 << 1), + FTCSR__CCLRA = (1 << 0), +}; +enum tcr_bits { + TCR__IEDGA__RISING_EDGE = (1 << 7), + TCR__CKS__INTERNAL_DIV8 = (0b00), + TCR__CKS__INTERNAL_DIV32 = (0b01), + TCR__CKS__INTERNAL_DIV128 = (0b10), + TCR__CKS__EXTERNAL_RISING = (0b11), +}; +enum tocr_bits { + TOCR__OCRS__OCRA = (0 << 4), + TOCR__OCRS__OCRB = (1 << 4), + TOCR__OLVLA = (1 << 1), + TOCR__OLBLB = (1 << 0), +}; +// enum vcra_bits { +#define VCRA__SERV(n) (n << 8) +#define VCRA__SRXV(n) (n << 0) +// }; +// enum vcrb_bits { +#define VCRB__STXV(n) (n << 8) +#define VCRB__STEV(n) (n << 0) +// }; +// enum vcrc_bits { +#define VCRC__FICV(n) (n << 8) // input-capture interrupt vector number +#define VCRC__FOCV(n) (n << 0) // output-compare interrupt vector number +// }; +// enum vcrd_bits { +#define VCRD__FOVV(n) (n << 8) +// };