shithub: psxe

ref: 6057aff755d8ad6ef6a0b624053a44eceeff4aab
dir: /psx/dev/timer.h/

View raw version
#ifndef TIMER_H
#define TIMER_H

#include <stdint.h>

#include "ic.h"
#include "gpu.h"

#define PSX_TIMER_BEGIN 0x1f801100
#define PSX_TIMER_SIZE  0x30
#define PSX_TIMER_END   0x1f80112f

/*
  0     Synchronization Enable (0=Free Run, 1=Synchronize via Bit1-2)
  1-2   Synchronization Mode   (0-3, see lists below)
         Synchronization Modes for Counter 0:
           0 = Pause counter during Hblank(s)
           1 = Reset counter to 0000h at Hblank(s)
           2 = Reset counter to 0000h at Hblank(s) and pause outside of Hblank
           3 = Pause until Hblank occurs once, then switch to Free Run
         Synchronization Modes for Counter 1:
           Same as above, but using Vblank instead of Hblank
         Synchronization Modes for Counter 2:
           0 or 3 = Stop counter at current value (forever, no h/v-blank start)
           1 or 2 = Free Run (same as when Synchronization Disabled)
  3     Reset counter to 0000h  (0=After Counter=FFFFh, 1=After Counter=Target)
  4     IRQ when Counter=Target (0=Disable, 1=Enable)
  5     IRQ when Counter=FFFFh  (0=Disable, 1=Enable)
  6     IRQ Once/Repeat Mode    (0=One-shot, 1=Repeatedly)
  7     IRQ Pulse/Toggle Mode   (0=Short Bit10=0 Pulse, 1=Toggle Bit10 on/off)
  8-9   Clock Source (0-3, see list below)
         Counter 0:  0 or 2 = System Clock,  1 or 3 = Dotclock
         Counter 1:  0 or 2 = System Clock,  1 or 3 = Hblank
         Counter 2:  0 or 1 = System Clock,  2 or 3 = System Clock/8
  10    Interrupt Request       (0=Yes, 1=No) (Set after Writing)    (W=1) (R)
  11    Reached Target Value    (0=No, 1=Yes) (Reset after Reading)        (R)
  12    Reached FFFFh Value     (0=No, 1=Yes) (Reset after Reading)        (R)
  13-15 Unknown (seems to be always zero)
  16-31 Garbage (next opcode)
*/
#define MODE_SYNCEN 0x0001
#define MODE_SYNCMD 0x0006
#define T0MD_HBLPAUSE 0
#define T0MD_HBLRESET 1
#define T0MD_HBLRANDP 2
#define T0MD_HBLOSHOT 3
// #define T1MD_VBLPAUSE 0
// #define T1MD_VBLRESET 1
// #define T1MD_VBLRANDP 2
// #define T1MD_VBLOSHOT 3
// #define T2MD_STOPMODE 0
// #define T2MD_FREEMODE 1
#define MODE_RESETC 0x0008
#define MODE_TGTIRQ 0x0010
#define MODE_MAXIRQ 0x0020
#define MODE_IRQRMD 0x0040
#define MODE_IRQPMD 0x0080
#define MODE_CLK 0x0080

typedef struct {
    uint32_t io_base, io_size;

    psx_ic_t* ic;

    struct {
        uint16_t prev_counter;
        uint16_t counter;
        uint32_t mode;
        uint32_t target;
        int paused;
        int irq_fired;
    } timer[3];
} psx_timer_t;

psx_timer_t* psx_timer_create();
void psx_timer_init(psx_timer_t*, psx_ic_t*);
uint32_t psx_timer_read32(psx_timer_t*, uint32_t);
uint16_t psx_timer_read16(psx_timer_t*, uint32_t);
uint8_t psx_timer_read8(psx_timer_t*, uint32_t);
void psx_timer_write32(psx_timer_t*, uint32_t, uint32_t);
void psx_timer_write16(psx_timer_t*, uint32_t, uint16_t);
void psx_timer_write8(psx_timer_t*, uint32_t, uint8_t);
void psx_timer_update(psx_timer_t*, int);
void psx_timer_destroy(psx_timer_t*);

// GPU event handlers
void psxe_gpu_hblank_event_cb(psx_gpu_t*);
void psxe_gpu_hblank_end_event_cb(psx_gpu_t*);
void psxe_gpu_vblank_timer_event_cb(psx_gpu_t*);
void psxe_gpu_vblank_end_event_cb(psx_gpu_t*);

#endif