diff --git a/src/saturn/Platform_Saturn.c b/src/saturn/Platform_Saturn.c index 6222e020c..2d386155a 100644 --- a/src/saturn/Platform_Saturn.c +++ b/src/saturn/Platform_Saturn.c @@ -91,36 +91,31 @@ void DateTime_CurrentLocal(struct cc_datetime* t) { /*########################################################################################################################* *--------------------------------------------------------Stopwatch--------------------------------------------------------* *#########################################################################################################################*/ -static volatile cc_uint32 overflow_count, wdt_overflows; +#include "sh2_wdt.h" -static void wdt_handler(void) { wdt_overflows++; } -static void ovf_handler(void) { overflow_count++; } +static void Stopwatch_Init(void) { + wdt_stop(); + + wdt_set_irq_number(CPU_INTC_INTERRUPT_WDT_ITI); + wdt_set_irq_priority(15); + cpu_intc_ihr_set(CPU_INTC_INTERRUPT_WDT_ITI, wdt_handler); + + wdt_enable(); +} cc_uint64 Stopwatch_Measure(void) { - return cpu_frt_count_get() | (overflow_count << 16); + return wdt_total_ticks(); } #define US_PER_SEC 1000000 -#define NTSC_320_CLOCK 26846588 +#define NTSC_320_CLOCK 26846587 cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; cc_uint64 delta = end - beg; // TODO still wrong?? PAL detection ??? - return (delta * US_PER_SEC) / (NTSC_320_CLOCK / 128); -} - -static void Stopwatch_Init(void) { - //cpu_frt_init(CPU_FRT_CLOCK_DIV_8); - cpu_frt_init(CPU_FRT_CLOCK_DIV_128); - cpu_frt_ovi_set(ovf_handler); - cpu_frt_interrupt_priority_set(15); - - //cpu_wdt_init(CPU_WDT_CLOCK_DIV_4096); - //cpu_wdt_interrupt_priority_set(15); - //cpu_wdt_timer_mode_set(CPU_WDT_MODE_INTERVAL, wdt_handler); - //cpu_wdt_enable(); + return (delta * US_PER_SEC) / (NTSC_320_CLOCK / 1024); } diff --git a/src/saturn/sh2_wdt.h b/src/saturn/sh2_wdt.h new file mode 100644 index 000000000..ed792bb30 --- /dev/null +++ b/src/saturn/sh2_wdt.h @@ -0,0 +1,73 @@ +static cc_uint32 wdt_overflows; + +// Interrupt Priority Request A +#define SH2_REG_IPRA ((volatile uint16_t *)0xFFFFFEE2) +#define SH2_IPRA_WDT_NUM 4 + +// Vector Number Setting Register WDT +#define SH2_REG_VCRWDT ((volatile uint16_t *)0xFFFFFEE4) +#define SH2_VCRWDT_NUM 8 + +// Watchdog Timer Counter +#define SH2_REG_WTCNT_R ((volatile uint8_t *)0xFFFFFE81) +#define SH2_REG_WTCNT_W ((volatile uint16_t *)0xFFFFFE80) +#define SH2_CMD_WTCNT(val) (0x5A00 | (uint8_t)(val)) + +// Watchdog Timer Control/Status Register +#define SH2_REG_WTCSR_R ((volatile uint8_t *)0xFFFFFE80) +#define SH2_REG_WTCSR_W ((volatile uint16_t *)0xFFFFFE80) +#define SH2_CMD_WTCSR(val) (0xA500 | (uint8_t)(val)) + +#define SH2_WTCSR_CLOCK_DIV_2 0 +#define SH2_WTCSR_CLOCK_DIV_64 1 +#define SH2_WTCSR_CLOCK_DIV_128 2 +#define SH2_WTCSR_CLOCK_DIV_256 3 +#define SH2_WTCSR_CLOCK_DIV_512 4 +#define SH2_WTCSR_CLOCK_DIV_1024 5 +#define SH2_WTCSR_CLOCK_DIV_4096 6 +#define SH2_WTCSR_CLOCK_DIV_8192 7 + +#define SH2_WTCSR_ENA_FLG 0x20 +#define SH2_WTCSR_OVF_FLG 0x80 + + +static CC_INLINE void wdt_set_irq_number(int irq_num) { + uint16_t vcrwdt = *SH2_REG_VCRWDT; + vcrwdt &= ~( 0x7F << SH2_VCRWDT_NUM); + vcrwdt |= (irq_num << SH2_VCRWDT_NUM); + + *SH2_REG_VCRWDT = vcrwdt; +} + +static CC_INLINE void wdt_set_irq_priority(uint8_t pri) { + uint16_t ipra = *SH2_REG_IPRA; + ipra &= ~(0xF << SH2_IPRA_WDT_NUM); + ipra |= (pri << SH2_IPRA_WDT_NUM); + + *SH2_REG_IPRA = ipra; +} + + +static void __interrupt_handler wdt_handler(void) { + uint8_t wtcr = *SH2_REG_WTCSR_R & ~SH2_WTCSR_OVF_FLG; + + *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(wtcr); + wdt_overflows++; +} + +static CC_INLINE void wdt_stop(void) { + *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(SH2_WTCSR_CLOCK_DIV_1024); +} + +static CC_INLINE void wdt_enable(void) { + uint8_t wtcr = *SH2_REG_WTCSR_R & ~SH2_WTCSR_OVF_FLG; + wtcr |= SH2_WTCSR_ENA_FLG; + // interval mode is 0 anyways + + *SH2_REG_WTCNT_W = SH2_CMD_WTCNT(0); + *SH2_REG_WTCSR_W = SH2_CMD_WTCSR(wtcr); +} + +static CC_INLINE uint32_t wdt_total_ticks(void) { + return (*SH2_REG_WTCNT_R) | (wdt_overflows << 8); +}