on-chip FRT experiment

This commit is contained in:
Zack Buhman 2023-01-09 17:54:50 -08:00
parent 843c7ce297
commit 76c4998664
3 changed files with 110 additions and 11 deletions

58
main.c
View File

@ -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;

2
scu.h
View File

@ -160,5 +160,3 @@ enum scu_vec {
};
static_assert(SCU_VEC__EXT15 == 0x5f);
extern reg32 vec[0x60] __asm("vec");

61
sh2.h
View File

@ -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)
// };